并查集+有向欧拉回路 有向欧拉通路的判定。
并查集用来判断是不是连通图。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=100010; int sumru[maxn],sumchu[maxn],father[30],flag[30],ff[30]; char s[1000]; int findd(int x) { if(x!=father[x]) father[x]=findd(father[x]); return father[x]; } int main() { int T; scanf("%d",&T); while(T--) { int n,i; scanf("%d",&n); memset(sumru,0,sizeof(sumru)); memset(sumchu,0,sizeof(sumchu)); memset(flag,0,sizeof(flag)); memset(ff,0,sizeof(ff)); for(i=0;i<=25;i++) father[i]=i; for(i=0;i<n;i++) { scanf("%s",s); sumru[s[strlen(s)-1]-'a']++; sumchu[s[0]-'a']++; int ft=findd(s[0]-'a'); int fw=findd(s[strlen(s)-1]-'a'); if(ft!=fw) father[ft]=fw; flag[s[strlen(s)-1]-'a']=1; flag[s[0]-'a']=1; } int jieguo=1,tott=0; int uu[maxn]; for(i=0;i<=25;i++) if(flag[i]==1) ff[findd(i)]=1; for(i=0;i<=25;i++) if(ff[i]==1) tott++; if(tott!=1)jieguo=0; tott=0; if(jieguo==1) { for(i=0;i<=25;i++) { if(sumru[i]==0&&sumchu[i]==0) continue;//这个点没有出现 if(sumru[i]==sumchu[i]) continue; if(sumru[i]!=sumchu[i]) { uu[tott]=i; tott++; } } if(tott!=2&&tott!=0) jieguo=0; if(tott==2) { if((sumru[uu[0]]-sumchu[uu[0]]==1&&sumru[uu[1]]-sumchu[uu[1]]==-1)||(sumru[uu[0]]-sumchu[uu[0]]==-1&&sumru[uu[1]]-sumchu[uu[1]]==1)) jieguo=jieguo; else jieguo=0; } } if(jieguo==0) printf("The door cannot be opened. "); else printf("Ordering is possible. "); } return 0; }