Play on Words

Play on Words

题意就是给你n个由小写字母构成的字符串,问你能不能将这n个字符串连接起来,B能接在A后面的条件是A的最后一个字母==B的第一个字母。

然后就是将26个小写字母看成顶点集,对于一个字符串,其首字母向尾字母连一条单向边构图,所以本题就是有向图的欧拉路问题。

代码:

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=35;

int in[N],out[N];
char s[N*100];
int used[26];
int par[26]; 

void init()    
{     
    for(int i=0;i<26;i++)    
        par[i]=i;    
}    
  
int find(int x)    
{    
    if(x!=par[x])    
       par[x]=find(par[x]);    
    return par[x];    
}

void union_(int x,int y)    
{    
    x=find(x);    
    y=find(y);    
    if(x!=y)    
       par[y]=x;    
}  
    
int main()
{
    int T,n;
    for(scanf("%d",&T); T--;)
    {
    	memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(used,0,sizeof(used));
        
    	init();
    	
        scanf("%d",&n);
        
        while(n--)
        {
            scanf("%s",s);
            int st=s[0],end=s[strlen(s)-1];
            st-='a',end-='a';
            union_(st,end);
            ++in[end];
            ++out[st];
            used[st]=1;
            used[end]=1;
        }
        
        int sum_root=0;//根结点的个数   
        for(int i=0;i<26;i++)    
           if(used[i]&&par[i]==i) 
		       sum_root++; 
        if(sum_root!=1)
        {
            puts("The door cannot be opened.");
            continue;
        }
        
        bool ok=1,k1=0,k2=0;
        for(int i=0; i<26; ++i)//一点入>出,一点出>入,其余出=入 
        {
            if(in[i]==out[i]) continue;
            else if(in[i]-out[i]==1&&!k1) k1=1;
            else if(out[i]-in[i]==1&&!k2) k2=1;
            else
            {
                ok=0;
                break;
            }
        }
        
        if(ok) puts("Ordering is possible.");
        else puts("The door cannot be opened.");
    }
}


猜你喜欢

转载自blog.csdn.net/m0_37846371/article/details/80328703
今日推荐