有向图的欧拉通路(半欧拉图):
1.连通(并查集)
2.一个节点入度-出度=1,另一个节点出度-入度=1,其余节点入度==出度
本题注意:还有欧拉回路的特殊情况
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
int n,T,fa[30],in[30],out[30];
char s[1005];
int Find(int x)
{
if(x!=fa[x])
fa[x]=Find(fa[x]);
return fa[x];
}
void Union(int x,int y)
{
int a=Find(x),b=Find(y);
if(a!=b)
fa[a]=b;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<26;i++)
fa[i]=i;
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
while(n--)
{
scanf("%s",s);
int u=s[0]-'a',v=s[strlen(s)-1]-'a';
in[u]++;
out[v]++;
Union(u,v);
}
int num=0;
for(int i=0;i<26;i++)//一个连通集
{
if(in[i]||out[i])//注意有些字母没出现
{
if(fa[i]==i)
num++;
}
}
int cnt=0,flag=0;//flag=0为欧拉回路
for(int i=0;i<26;i++)
{
//注意有些字母没出现,所以入度出度都为0,但有一种欧拉回路,入度==出度需特判
if(in[i]!=out[i])//入度!=出度
{
cnt++;
if(abs(in[i]-out[i])!=1)
flag=1;
}
}
if(num==1&&flag==0&&(cnt==0||cnt==2))
printf("Ordering is possible.\n");
else
printf("The door cannot be opened.\n");
}
return 0;
}