题目链接:http://poj.org/problem?id=1386
每一个单词对应一条单向边,从首字母指向尾字母,问题转化为在图中是否存在欧拉回路/通路。
Hint:欧拉回路/欧拉通路要求基图联通,意思是不存在孤立的点,而不是整个图只有一个联通块。判断基图联通可以用并查集。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char buf[2000];
int fa[30];
int flag;
bool used[30];
int ind[30],ond[30];
int cnt=0,T,n;
int getfa (int x) {
if (x==fa[x]) return x;
fa[x]=getfa(fa[x]);
return fa[x];
}
int main () {
int fa1,fa2,u,v,tmp,len;
scanf("%d",&T);
while (T--) {
flag=0;
scanf("%d",&n);
memset(used,0,sizeof(used));
memset(ind,0,sizeof(ind));
memset(ond,0,sizeof(ond));
for (int i=0;i<26;i++) fa[i]=i;
for (int i=1;i<=n;i++) {
scanf("%s",buf);len=strlen(buf);
u=buf[0]-97; v=buf[len-1]-97;
tmp=v;
++ind[v],++ond[u];
used[u]=used[v]=1;
fa1=getfa(u);fa2=getfa(v);
if (fa1!=fa2) fa[fa1]=fa2;
}
tmp=getfa(tmp);//这里不能是fa[tmp],还要再研究下
for (int i=0;i<26;i++) if (used[i]&&getfa(i)!=tmp) {flag=1;puts("The door cannot be opened.");break;}
if (flag) continue;
tmp=0;cnt=0;flag=0;
for (int i=0;i<26;i++)
if (used[i]&&ind[i]!=ond[i]) {
if ((++cnt)==3) { flag=1;break; }
if (cnt==1) {
if ((ond[i]-ind[i])==-1||(ond[i]-ind[i])==1) tmp=ond[i]-ind[i];
else {
flag=1;break;
}
}
else if (tmp+ond[i]-ind[i]!=0) {
flag=1;break;
}
}
if (flag) puts("The door cannot be opened.");else puts("Ordering is possible.");
}
}