2019 UESTC ACM Training for Graph[C] (字典序最小的欧拉回路/道路)

知识共享许可协议 Creative Commons

题意大概为找到一个字典序最小的欧拉道路/回路,不过数据范围给的异常的大,所以应该是要对做法有一些要求。
对于一条欧拉道路,需要有向图中存在且仅存在一对点,使得一个点的入读比出度大一(这个点即为最终到达的点),另一个点出度比入读大一(这个点即为初始点)。
对于一条欧拉回路,需要有向图中所有点的入读=出度。
当然,进行以上两个判定之前,还需要保证给出的图所有的边都联通(这一点可以用并查集解决)。
因此我们只需要判断这两个条件是否满足即可。
需要注意的是,在寻找路径的函数进行回溯的时候,如果使用打标记的方法判定某条边是否走过,其实在枚举的时候还是会枚举到,最后还是会TLE。所以可以对每个点用优先队列存储能到达的点,在寻找路径的时候以能到达的点从小到大的顺序进行搜索。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<map>
#define LL long long
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
struct Edge{
	int from,to;
	bool operator <(const Edge& h)const{
		return from==h.from?to>h.to:from>h.from;
	}
}edges[maxn<<1],ans[maxn<<1];
int n,m,rd[maxn],cd[maxn],mark[maxn],fa[maxn],cnt,tot;
priority_queue<Edge>q[maxn];
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
void euler(int u){
	while(q[u].size()){
		int v=q[u].top().to;q[u].pop();
		euler(v);
		ans[++tot]=(Edge){u,v};
	}
}
int main(){
	_read(n);_read(m);
	for(int i=1;i<=n;i++)fa[i]=i;
	int s=n;
	for(int i=1;i<=m;i++){
		int x,y;
		_read(x);_read(y);
		edges[i].from=x;
		edges[i].to=y;
		mark[x]=mark[y]=1;
		rd[y]++,cd[x]++;
		int fx=getfa(x),fy=getfa(y);
		if(fx!=fy)fa[fx]=fy;
		s=min(s,x);
	}
	int c1=0,c2=0;
	for(int i=1;i<=n;i++)
		if(mark[i]){
			if(rd[i]==cd[i])continue;
			else if(rd[i]==cd[i]+1)c1++;
			else if(cd[i]==rd[i]+1)c2++,s=i;
			else {
				puts("What a shame!");
				return 0;
			}
		} 
	int flag=0;
	for(int i=1;i<=n;i++)
		if(mark[i]&&getfa(i)==i)flag++;
	if(((c1==c2&&c1==0)||(c1==c2&&c1==1))&&flag==1){
		for(int i=1;i<=m;i++)q[edges[i].from].push((Edge){edges[i].from,edges[i].to});
		euler(s);
		for(int i=tot;i>=1;i--)
			if(i==tot)printf("%d %d ",ans[i].from,ans[i].to);
			else printf("%d ",ans[i].to);
	}
	else {
		puts("What a shame!");
		return 0;
	}
}

猜你喜欢

转载自blog.csdn.net/getsum/article/details/91845174
今日推荐