题目链接:传送门
思路:
(1)将每个单词视为有向路径,单词的起始字母是起始节点,末尾字母是终止节点,然后找由字母建立的有向图
是否是欧拉图或者半欧拉图。
(2)先用并查集判断是否连通,再判断入度与出度的·关系是否符合要求。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn = 100100; int fa[120],in[120],out[120]; string ss[maxn]; struct Edge{ int to,next,id; }edge[maxn*2]; int vis[maxn],head[maxn],tot; int f(int x) { if(fa[x]==0) return x; else return fa[x]=f(fa[x]); } void Init() { memset(fa,0,sizeof(fa)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); memset(head,0,sizeof(head)); tot=0; } void add(int x,int y,int w) { edge[tot].to=y; edge[tot].next=head[x]; edge[tot].id=w; head[x]=tot++; } int main(void) { //printf("%d\n",'z'-'a'+1); int N,i,n,j,x,y,t1,t2; scanf("%d",&N); while(N--){ scanf("%d",&n); Init(); for(i=1;i<=n;i++){ cin>>ss[i]; x=ss[i][0]-'a'+1; y=ss[i][ss[i].length()-1]-'a'+1; t1=f(x);t2=f(y); if(t1!=t2) fa[t2]=t1; in[y]++; out[x]++; add(x,y,i); } int fg=1; x=f(x); for(i=1;i<=n;i++){ y=ss[i][0]-'a'+1; if(f(y)!=x){ fg=0;break; } y==ss[i][ss[i].length()-1]-'a'+1; if(f(y)!=x){ fg=0;break; } } if(fg==1){ int tt=1,cc=0; for(i=1;i<=26;i++){ if(abs(in[i]-out[i])>1){ tt=0;break; } else if(abs(in[i]-out[i])==1){ cc+=(in[i]-out[i]); } } if(tt==1&&cc==0) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } else printf("The door cannot be opened.\n"); } return 0; }