本题其实是将26个字母作为点(如果所有的单词的第一个单词或者最后一个单词出现过),每个单词是一个桥。则就和著名的“七桥问题”相似了。也就是这个题可以当作判断是否是欧拉路问题。如果每个点的入度等于出度,就是欧拉回路。如果有两个点是一个入度比出度大1,一个是出度比入度大1是欧拉道路。
在这之前要判断所有点是否连通,可以变成无向图来判断。
#include <iostream>
#include <cstring>
#include<cstdio>
#include <queue>
using namespace std ;
char ch[100011][1100];
int you[30];
int map[30][30];
int node[30];
bool dfs(int i)
{
int j;
for(j=0; j<26; ++j)
{
if(you[i])
if(map[i][j])
{
if(node[j]!=1)
{
node[j]=1;
dfs(j);
}
}
}
}
int main()
{ //freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
memset(map,0,sizeof(map));
int n;
memset(you,0,sizeof(you));
int in[30]= {0},out[30]= {0};
memset(node,0,sizeof(node));
scanf("%d",&n);
int i;
int l[100011];
for(i=0; i<n; ++i)
{
scanf("%s",ch[i]);
l[i]=strlen(ch[i]);
++you[ch[i][0]-'a'];
++you[ch[i][l[i]-1]-'a'];
++out[ch[i][0]-'a'];
++in[ch[i][l[i]-1]-'a'];
map[ch[i][0]-'a'][ch[i][l[i]-1]-'a']=1;
map[ch[i][l[i]-1]-'a'][ch[i][0]-'a']=1;
}
for(i=0;i<26;++i)
{
if(you[i])
{node[i]=1;break;}
}
int flag=1;
for(i=0; i<26; ++i)
{
if(you[i])
{
if(node[i]==0)
{
flag=0;
break;
}
dfs(i);
}
}
int s1,s2,ge=0;
if(!flag)
{
printf("The door cannot be opened.\n");
}
else
{
for(i=0; i<26; ++i)
{
if(you[i])
{
if(in[i]!=out[i])
{
++ge;
if(ge>2)
{
flag=0;
break;
}
if(ge==1)
{
s1=i;
}
else
{
s2=i;
}
}
}
}
//cout<<ge<<"ge\n";
if(!flag)
{
printf("The door cannot be opened.\n");
}
else
{
if(ge==2)
{ // cout<<in[s1]<<" "<<out[s1]<<" "<<in[s2]<<" "<<out[s2]<<endl;
if(!((in[s1]-out[s1]==1&&out[s2]-in[s2]==1)||(in[s1]-out[s1]==-1&&out[s2]-in[s2]==-1)))
flag=0;
}
if(flag)
{
printf("Ordering is possible.\n");
}
else printf("The door cannot be opened.\n");
}
}
}
return 0 ;
}