单词接龙——欧拉路径

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;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/82011494