HDU 1116 Play on Words (并查集+有向图的欧拉路)

题意:类似于成语接龙,给你若干个单词,问你能否组成一个排列,使得一个单词的尾字母和后面一个单词的首字母相同。例如

acm,malform,mouse这三个单词就满足题意。

思路:把每个单词看成一条边,取首字母和尾字母,作为起点和终点。那么我们可以构造一个图,图上有26个字母,每输入一个单词,我们就在对应的两点间建立一条有向边,注意是有向边。至于为什么是有向边,请读者自己思考。要判断我们输入的单词是否满足题意,其实就是判断图中是否存在一条欧拉路径。当然,如果这个图不只包含一个连通分量,那么一定不满足题意。连通分量用并查集维护。

下面的问题就是判断有向图的欧拉路径。如果不是回路,那么图中只有一个点的出度比入度大1(起点),一个点的出度比入度小1(终点),其他点出度等于入度。如果是欧拉回路,那么要求所有的点出度等于入度。当然,如果存在出度入度的差值大于1的点也一定不能形成欧拉路。

以下是代码:变量的含义为

num记录连通块的个数,indeg数组记录每个点的入度,outdeg数组记录每个点的出度,vis数组是访问标记,flag标记是否存在出度入度的差值大于1的点。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int p[30];

int Find(int x)
{
    if(x!=p[x])
        p[x]=Find(p[x]);
    return p[x];
}

void join(int a,int b)
{
    if(Find(a)!=Find(b))
        p[Find(a)]=Find(b);
}


int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int t,num,num1,num2;
    cin>>t;
    int indeg[30],outdeg[30];
    bool vis[30],flag;
    while(t--)
    {
        num=num1=num2=0;
        flag=true;
        int n;
        cin>>n;
        char str[1000];
        for(int i=0; i<26; i++)
        {
            p[i]=i;
            vis[i]=false;
            outdeg[i]=indeg[i]=0;
        }
        
        
        for(int i=0; i<n; i++)
        {
            cin>>str;
            join(str[0]-'a',str[strlen(str)-1]-'a');
            indeg[str[0]-'a']++;
            outdeg[str[strlen(str)-1]-'a']++;
            vis[str[0]-'a']=true;
            vis[str[strlen(str)-1]-'a']=true;
        }
        
        for(int i=0; i<26; i++)
        {
            if(p[i]==i&&vis[i])
                num++;
            if(indeg[i]-outdeg[i]==1)
                num1++;
            if(outdeg[i]-indeg[i]==1)
                num2++;
            if(indeg[i]-outdeg[i]>1||outdeg[i]-indeg[i]>1)
                flag=false;
        }
        
        if(flag==true&&num==1&&(num1==num2==0||num1==num2==1))
        {
            cout<<"Ordering is possible."<<endl;
        }
        else cout<<"The door cannot be opened."<<endl;
    }
}


猜你喜欢

转载自blog.csdn.net/zero___zero/article/details/80902937