题目大意:
给一堆字母,让它们进行接龙,要头对尾能够接的上,问有没有一种方法让所有成语都完成接龙
这道题实际上是在考虑是否存在一条欧拉通路,每个单词产生一条有向线段,由第一个字母指向最后一个字母
这道题另一个需要考虑的是是否所有存在的字母都是处于一个连通分量中的,这里我们考虑用并查集来解决问题。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int fa[],in[],out[],visit[];
char str[];
int find_head(int x)
{
int u=x;
while(x!=fa[x]){
x=fa[x];
}
fa[u]=x;
return x;
}
int Union(int x,int y)
{
int fa_x=find_head(x);
int fa_y=find_head(y);
if(fa_x!=fa_y){
fa[fa_x]=fa_y;
}
return fa_y;
}
int main()
{
int T,n,tmp;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(in,,sizeof(in));
memset(out,,sizeof(out));
memset(visit,,sizeof(visit));
for(int i=;i<=;i++) fa[i]=i;
for(int i=;i<n;i++){
scanf("%s",str);
int len=strlen(str);
out[str[]-'a'+]++;
in[str[len-]-'a'+]++;
tmp=Union(str[]-'a'+,str[len-]-'a'+);//记录那个唯一的头结点
//cout<<tmp<<endl;
visit[str[]-'a'+]=;
visit[str[len-]-'a'+]=;
}
bool flag=true;
for(int i=;i<=;i++){
if(visit[i]){
if(find_head(i)!=tmp){flag=false;break;}
}
}
int cnt1=,cnt2=;
for(int i=;i<=;i++){
if(visit[i]){
if(in[i]-out[i]==) cnt1++;
else if(out[i]-in[i]==) cnt2++;
else if(in[i]!=out[i]) {flag=false;break;}
}
}
if(!flag){
printf("The door cannot be opened.\n");
//continue;
}
else if((cnt1==&&cnt2==)||(cnt1==&&cnt2==)) puts("Ordering is possible.");
else puts("The door cannot be opened.");
}
return ;
}