#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#define maxn 30
using namespace std;
int vis[maxn],N,T,f[maxn],in[maxn],out[maxn];
void init()
{
for(int i=0;i<maxn;i++)
{
f[i]=i;
}
}
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
}
void Union(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
f[x]=y;
}
int main()
{
scanf("%d",&T);
while(T--){
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
char str[1005];
init();
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%s",str);
++out[str[0]-'a'];
++in[str[strlen(str)-1]-'a'];
Union(str[0]-'a',str[strlen(str)-1]-'a');
}
int cnt=0;
for(int i=0;i<27;i++){
if((in[i]||out[i])&&find(i)==i)
++cnt; //计算连通度
}
bool flag=true;
if(cnt!=1) flag=false;
int num1=0,num2=0;
for(int i=0;i<maxn;i++){
if(!flag) break;
if(in[i]!=out[i]){
if(in[i]==out[i]+1) ++num1;
else if(out[i]==in[i]+1) ++num2;
else{
flag=false; break;
}
}
}
if(num1&&num2&&num1+num2>2) flag=false;
if(flag)
printf("Ordering is possible.\n");
else
printf("The door cannot be opened.\n");
}
return 0;
}
字母看成节点 ,单词看成有向边
例如
acm->malform->mouse
out in out in out in
a---->m m--->m m---->e
a---------m-----------m-------e
out[a] 1
in[m] 2
out[m] 2
in[e] 1