UVA - 10129 Play on Words (欧拉回路+并查集)
思路:
分别存下每个字符串的首尾字符,以字符为结点,单词看作一条变,就变成了求欧拉回路了,先判断下图是否连通,然后根据欧拉回路的结论:最多只能有两个点的入读不等于初读,而且必须是一个点的出度恰好比入度大1(将它作为起点),另一个的入度比出度大1(将它作为终点);
实现代码:
#include<iostream> #include<cstring> using namespace std; const int M = 30; int f[M]; int in[M],out[M]; int fd(int x) {return f[x]==x? x:f[x]=fd(f[x]);} void mix(int a,int b) {a=fd(a);b=fd(b);if(a!=b) f[a]=b;} void init(){ for(int i = 0;i <= M;i ++){ f[i] = i; } memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); } int main() { string s; int t,n; cin>>t; while(t--){ init(); cin>>n; for(int i = 0;i < n;i ++){ cin>>s; int len = s.size(); int x = s[0] - 'a'; int y = s[len-1] - 'a'; in[x]++; out[y]++; //cout<<x<<" "<<y<<endl; mix(x,y); } int ans = 0; for(int i = 0;i < 26;i ++){ if(i==f[i]&&(in[i]||out[i])){ ans++; } } //cout<<ans<<endl; bool flag = true; int num1 = 0,num2 = 0; if(ans == 1){ for(int i=0;i<=26;i++){ if(in[i]!=out[i]){ if(in[i]+1==out[i]) num1++; else if(in[i]==out[i]+1) num2++; else{ flag = false;break; } } } if(num1&&num2&&num1+num2>2) flag = false; } else flag = false; if(flag) cout<<"Ordering is possible."<<endl; else cout<<"The door cannot be opened."<<endl; } return 0; }