需要了解几个知识:并查集(见《算法竞赛入门经典》第11章。)把26个字母当做节点,每个单词表示一条边。用这样的方式建图,比较入度与出度的大小关系即可。见《算法竞赛入门经典》第六章欧拉回路相关知识。另外,如果读取的字符数组开的不够大,会引起runtime error错误。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=1010,maxm=30;
char s[maxn];//not char s[maxm]
int in[maxm],out[maxm],p[maxm];//indgree,outdgree
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("10129.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
while(T--)
{
int i,N;
scanf("%d",&N);
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(i=0;i<26;i++) p[i]=i;
for(i=0;i<N;i++)
{
scanf("%s",&s);
int first=s[0]-'a';
int last=s[strlen(s)-1]-'a';
out[first]++;
in[last]++;
first=find(first);
last=find(last);
if(first!=last)
p[first]=last;
}
for(i=0;!in[i] && !out[i];i++);
bool ok=true;
int t=find(i),j=i;
for(i++;i<26;i++)
if((in[i] || out[i]) && find(i)!=t)
{
ok=false;
break;
}
t=0;
if(ok)
{
for(i=j;i<26;i++)
{
int k=abs(in[i]-out[i]);
if(k>1)
{
ok=false;
break;
}else if(k==1) t++;
}
}
if(!ok || t>2) printf("The door cannot be opened.\n");
else printf("Ordering is possible.\n");
}
return 0;
}