我的思路:
用俩个数组分别记录出现过的节点的入度和出度,这样只有一个字母的入度比出度大1,一个字母的出度比入度大1,或者是所有有字母的出度和入度都一样,他就是欧拉路
但这样还差了一个联通性的判断 于是我用了一个辅助数组 f[] 用并查集的方式判断是否连通
代码:
#include<iostream> #include<string> using namespace std; int f[30],c[30],r[30]; char s[1005]; int find(int x) { if(x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } void Union(int x,int y) { int a=find(x); int b=find(y); if(a==b) return ; f[a]=b; return ; } void init() { for(int i=0;i<26;i++) f[i]=i; memset(c,0,sizeof(c)); memset(r,0,sizeof(r)); } int main() { int i,j,cas,n; cin>>cas; while(cas--) { init(); cin>>n; for(i=0;i<n;i++) { cin>>s; int a=s[0]-'a'; int b=s[strlen(s)-1]-'a'; Union(a,b); r[b]++; c[a]++;//累加 节点的入度和出度 } int count=0; for(i=0;i<26;i++)//计算根节点数目 { if(i==find(i)&&(r[i]||c[i])) count++; } if(count!=1)//判断是否连通 { cout<<"The door cannot be opened."<<endl; continue; } int p1=0,p2=0; for(i=0;i<26;i++) { if(c[i]>r[i]) p1+=c[i]-r[i]; if(r[i]>c[i]) p2+=r[i]-c[i]; } if((p1==0&&p2==0)||(p1==1&&p2==1)) cout<<"Ordering is possible."<<endl; else cout<<"The door cannot be opened."<<endl; } return 0; }