Description
相信大家都玩过单词接龙。小明的爸爸设计了一个单词接龙密码,连续两个单词,前一个的尾字母和后一个的首字母必须相同(“acm”后面可以接如“motorola”)。若能把所有的单词都连起来,那么就可以解开密码,拿到零花钱。
现在有N天,就有N个密码。现在请你帮忙给出,小明有多少天可以拿到零花钱。
Input
第一行一个整数T(1<=T<=10)表示天数。
每天第一行一个整数N(1<=N<=100000)表示单词个数。
接下来N行,每行一个由小写字母构成的单词,单词长度在[2,1000]。
Output
T行,输出“Yes”或者“No”,表示能否解开密码。
Sample Input
3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
Sample Output
No
Yes
No
刚开始是想用出现次数什么的来算,结果第二个样例过不去,后来搜了才知道是新的东西叫欧拉路径
就是用并查集来看是否全联通并且只有一条道路,还要考虑环的情况
#include<iostream>
#include<string.h>
using namespace std;
int fa[30],head[30],en[30],vis[30];
int finds(int x)
{
return x==fa[x]?fa[x]:fa[x]=finds(fa[x]);
}
void match(int x,int y)
{
int fax=finds(x);
int fay=finds(y);
if(fax!=fay)
fa[fay]=fax;
}
int main()
{
int t,n,sta,fin;
string s;
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<=26;i++)
{
fa[i]=i;
head[i]=en[i]=vis[i]=0;
}
for(int i=1;i<=n;i++)
{
cin>>s;
sta=s[0]-'a';
fin=s[s.length()-1]-'a';
vis[sta]=vis[fin]=1;
head[sta]++;
en[fin]++;
match(sta,fin);
}
int flag=1;
int root=0;
sta=fin=0;
for(int i=0;i<26;i++)
{
if(fa[i]==i&&vis[i])
root++;
if(head[i]!=en[i])
{
if(head[i]-en[i]==1)
sta++;
else if(en[i]-head[i]==1)
fin++;
else
flag=0;
}
}
if(root>1)
flag=0;
if(flag&&sta==0&&fin==0)
cout<<"Yes"<<endl;
else if(flag&&sta==1&&fin==1)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}