就是Catenyms的简略版,只是无需保存路径。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int fa[26+5]; //并查集
int in[26+5],out[26+5];//入度,出度
bool mark[26+5]; //mark[i]=true,表i这个字母被用到作为图顶点了
int m;//单词数,即边数
int findset(int u)
{
if(fa[u]==-1) return u;
return fa[u]=findset(fa[u]);
}
bool ok()//判断是否弱连通图
{
int k=0;
for(int i=0;i<26;i++)if(mark[i])
if(findset(i)==i) k++;
return k==1;
}
void init()
{
memset(fa,-1,sizeof(fa));
memset(mark,0,sizeof(mark));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
}
int main()
{
int n;
string str[100010];
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
cin>>str[i];
int u,v;
u=str[i][0]-'a';
int yyy=str[i].length()-1;
v=str[i][yyy]-'a';//表示该边还未被访问
mark[u]=mark[v]=true;
in[v]++, out[u]++;
u=findset(u), v=findset(v);
if(u!=v) fa[u]=v; //合并连通分量
}
int i,c1=0,c2=0; //错误1,这里c1与c2忘了初始化
for(i=0;i<26;i++)if(mark[i])
{
if(in[i]==out[i]) continue;
else if(in[i]-out[i]==1) c1++;
else if(out[i]-in[i]==1) c2++;
else break;
}
if(i==26&&((c1==c2&&c1==0)||(c1==c2&&c1==1)) && ok() )//所有点度符合要求且弱连通
{
printf("Ordering is possible.\n");
}
else printf("The door cannot be opened.\n");
}
return 0;
}