题意:给N个单词,问能不能把所有的单词串起来。模型就是欧拉回路或者欧拉路径。
解:
只有26中字母,每种字母作为一个点。每个单词的首字母和尾字母连条单向边。
如果是欧拉回路,那么所有点的入度等于出度。
如果是欧拉路径,那么只有两个点的入度不等于出度,其一是起始点,出度比入度大1,另一个是结束点,入度比出度大1
显然,如果给的图由多个连通图构成,显然不能(并查集维护)。接下来就只需判断是欧拉回路还是欧拉路径,这两种都是可以的。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
#include <map>
#include <set>
using namespace std;
#define MAXN 1005
#define LL long long
int in[MAXN],out[MAXN];
char ch[1005];
int vis[MAXN],fa[MAXN];
int findfa(int x)
{
if(x==fa[x])return x;
return fa[x]=findfa(fa[x]);
}
int main()
{
int i,t,n,flag,tx,ty,len;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(i=1;i<=30;i++)fa[i]=i;
for(i=1;i<=n;i++)
{
scanf("%s",ch+1);
len=strlen(ch+1);
int u=ch[1]-'a'+1;
int v=ch[len]-'a'+1;
out[u]++;
in[v]++;
tx=findfa(u);
ty=findfa(v);
if(tx!=ty)
{
fa[tx]=ty;
}
}
flag=0;
tx=findfa(tx);
for(i=1;i<=27;i++)
{
if(in[i]==0&&out[i]==0)continue;
ty=findfa(i);
if(tx!=ty)
{
flag=1;break;//如果两个点的祖先不同,那么说明他们属于不同的连通图。
}
}
if(flag){puts("The door cannot be opened.");continue;}
flag=0;
for(i=1;i<=27;i++)//先判断是不是欧拉回路
{
if(in[i]==0&&out[i]==0)continue;
if(in[i]!=out[i])
{
flag=1;continue;
}
}
if(flag==0){puts("Ordering is possible.");continue;}
int f1=0,f2=0,f3=0;
for(i=1;i<=27;i++)//在判断是不是欧拉路径
{
if(in[i]==0&&out[i]==0)continue;
if(in[i]!=out[i])f3++;
if(in[i]+1==out[i])f1++;
if(out[i]+1==in[i])f2++;
}
if(f3==2&&f1==1&&f2==1)//欧拉路径只有两个点的入度不等于初度,且差为1.
{
puts("Ordering is possible.");
}
else puts("The door cannot be opened.");
}
return 0;
}