- 原题链接:Here!,大白皮原题
- 分析:
题目大意是输入n个单词,判断是否可以排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同。
可以把每个单词看成一个有向边,单词的第一个和最后一个字母看成节点,这样问题便转化成了判断图中是否存在欧拉路径的问题。
- 欧拉路径存在的充分条件:1.是一个连通图(并查集实现) 2.最多有两个奇点(度为奇数的点)
- CODE:
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 1000+10; int pa[256]; // 并查集 int used[256],deg[maxn]; // 字母是否出现过;每个点度数 int cc; // 连通块个数 int findset(int x){ return x!=pa[x]?findset(pa[x]):x; } void init(){ memset(used,0,sizeof(used)); memset(deg,0,sizeof(deg)); for(int ch='a';ch<='z';ch++) pa[ch]=ch; cc = 26; } int main(){ int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); init(); char words[maxn]; for(int i=0;i<n;i++){ scanf("%s",words); char c1=words[0] , c2=words[strlen(words)-1]; deg[c1]++; deg[c2]--; used[c1]=used[c2]=1; int f1=findset(c1) , f2=findset(c2); if(f1!=f2){ pa[f1]=f2; cc--; } } vector<int> d; for(int ch='a';ch<='z';ch++){ if(!used[ch]) cc--; else if(deg[ch]!=0) d.push_back(deg[ch]); } bool ok=false; if( cc==1 && ( d.empty() || ( d.size()==2 && ( d[0]==1 || d[0]==-1 ))) ) ok=true; if(ok) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } return 0; }
HDU 2894 Play On Words(欧拉回路)
最新推荐文章于 2020-08-24 21:39:31 发布