其他分享
首页 > 其他分享> > CF508D Tanya and Password 欧拉路径

CF508D Tanya and Password 欧拉路径

作者:互联网

题意:

戳这里

分析:

很容易想到把每个单词转化为一条边,把每两个字母看成一个点,一个单词相当于连接了两个点

ex : \(abc\) 相当于一条边 \(ab\to bc\)

然后判断是否存在一条欧拉路径,有向图欧拉路径的判断条件:

  1. 转化为无向边之后图联通
  2. 每个点出/入度相同,或者最多有两个点入度不等于出度,其中一个入度比出度大 \(1\) 一个出度比入度大 \(1\) 且后者必须作为起点

至于求欧拉路径的话直接 \(dfs\) 然后加点倒序输出

必须倒序输出,因为正序输出无法保证最后遍历到的点一定是终点,而倒序加点输出保证了最后访问的点一定是终点,因为只有终点无法继续向下遍历,此时就会最先入队

tip : 存边的时候必须用 \(vector\) 或者像网络流的当前弧优化一样这样才能保证复杂度,每条边只会被遍历一遍

代码:

#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define pb push_back
#define fir first
#define sec second
#define inl inline
#define reg register

using namespace std;

namespace zzc
{
	typedef long long ll;
	inline int read()
	{
		int x=0,f=1;char ch=getchar();
		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
		return x*f;
	}
	
	const int maxn = 2e5+5;
	int deg[maxn],fa[maxn],num[maxn],head[maxn];
	int n,cnt[maxn],st;
	char ch[5];
	bool vis[maxn];
	string ans;
	vector<int> e[maxn];
	
	void add(int u,int v)
	{
		e[u].pb(v);
	}
	
	int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
	
	void merge(int x,int y)
	{
		int fx=find(x),fy=find(y);
		if(fx!=fy) fa[fy]=fx;
	}
	
	inl int mark(char a,char b)
	{
		return a*128+b;
	}
	
	void dfs(int u)
	{
		while(cnt[u]<(int)e[u].size()) dfs(e[u][cnt[u]++]);
		ans+=(char)(u%128);
	}
	
	bool check()
	{
		int tmp1=0,tmp2=0;
		st=mark(ch[1],ch[2]);
		for(int i=0;i<=17000;i++)
		{
			if(num[i])
			{
				if(find(i)==i) tmp1++;
				if(deg[i])
				{
					if(deg[i]>1||deg[i]<-1) return false;
					if(deg[i]==1) st=i;
					tmp2++;
				}
			}
		}
		if(tmp1>1) return false;
		if(tmp2&&tmp2!=2) return false;
		return true;
	}
	
	void work()
	{
		n=read();
		for(int i=1;i<=17000;i++) fa[i]=i; 
		for(int i=1;i<=n;i++)
		{
			scanf("%s",ch+1);	
			add(mark(ch[1],ch[2]),mark(ch[2],ch[3]));
			merge(mark(ch[1],ch[2]),mark(ch[2],ch[3]));
			deg[mark(ch[1],ch[2])]++;
			deg[mark(ch[2],ch[3])]--;
			num[mark(ch[1],ch[2])]++;
			num[mark(ch[2],ch[3])]++;
		}
		if(!check())
		{
			puts("NO");
			return ;
		}
		else puts("YES");
		dfs(st);
		ans+=(char)(st/128);
		reverse(ans.begin(),ans.end());
		cout<<ans<<endl;
	}

}

int main()
{
	zzc::work();
	return 0;
}

标签:return,int,void,Tanya,fa,CF508D,Password,find,欧拉
来源: https://www.cnblogs.com/youth518/p/14328550.html