这是一道欧拉回路的简单题目,对于初学者的理解很有帮助,所以把它分享一下。这是一个有向图。
这道题大意可抽象为把26个字母个字母看做点(所以这里我们需要把字母与点进行转化),然后把一些点联通到一起,判断最后可不可以组成线或者环。
组成线的条件为所有点都将通过其他点链接到一个父亲节点上,而组成环的条件为所有点都与其他点相连并且出度=入度,只有两个点入度与出度差1,。
题中涉及一些并差集相关知识,来计算图中有几条线。
注:所有点必须用上。
#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int in[27];
int out[27];
int father[27];
int finds(int x)
{
while(father[x]!=x)
x=father[x];
return x;
}
void unite(int x,int y)
{
father[finds(y)]=finds(x);
}
int main()
{
char s[1000+5];
int t,n;
int x; //入度
int y; //出度
cin>>t;
while(t--)
{
for(int i=0;i<=26;i++)
{
father[i]=i;
in[i]=0;
out[i]=0;
}
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s;
x=s[0]-'a';
y=s[strlen(s)-1]-'a';
unite(x,y);
in[x]++;
out[y]++;
}
int num1=0;//记录入度数不等于出度数的点的个数,即非联通点的个数
int num2=0;//记录点联通后有几条线
int num3=0;//记录线中点的个数
int m=0; // 记录出现点数
for(int i=0;i<=26;i++)
{
if(in[i]==0&&out[i]==0) continue;//如果点没出现,不记录点的个数
m++;
if(abs(in[i]-out[i])==1) num1++;
if(in[i]==out[i]) num3++;
if(finds(i)==i) num2++;
}
if(num2==1&&(num3==m||(num3==m-2&&num1==2)))
cout<<"Ordering is possible."<<endl;
else
cout<<"The door cannot be opened."<<endl;
}
}