hdu 1116 Play on Words(欧拉图)

1.题意:给n个单词,问是否能按成语接龙的方式将所有的单词串连起来。

2.思路:把单词看成是从首字母到尾字母的有向边(弧)即可。只要该有向图是欧拉图,那么就可以连。否则不可以。写并查集中的Union的时候要注意是a=Find(a);不要再重复犯错了

3.代码:

#include
#include
using namespace std;

int father[30];
char s[1005];
int in[30],out[30];
int vis[30];
int deta[30];
int mat[30][30];

int f(int a)
{
    return a>0?a:-a;
}

int Find(int a)
{
    int r=a;
    while(father[a]!=a)
    {
        a=father[a];
    }
    father[r]=a;
    return a;
}

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

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        memset(mat,0,sizeof(mat));
        scanf("%d",&n);
        for(int i=1; i<=26; i++)
        {
            father[i]=i;
            in[i]=out[i]=0;
            vis[i]=0;
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%s",s);
            int len=strlen(s);
            int a,b;
            a=s[0]-'a'+1;
            b=s[len-1]-'a'+1;


            in[a]++;
            out[b]++;
            vis[a]=vis[b]=1;
            if(mat[a][b]==0&&mat[b][a]==0)
            {
                Union(a,b);
                mat[a][b]=mat[b][a]=1;
            }
        }
        int cnt=0;
        int cnt1=0;
        for(int i=1; i<=26; i++)
        {
            if(Find(i)==i&&vis[i]==1)
                cnt++;
            if(vis[i]==1&&in[i]!=out[i])
            {
                cnt1++;
                deta[cnt1]=in[i]-out[i];
            }
        }
        if(cnt==1&&(cnt1==0||(cnt1==2&&f(deta[1])==1&&f(deta[2])==1)))
        {
            printf("Ordering is possible.\n");
        }
        else
            printf("The door cannot be opened.\n");
    }
    return 0;
}

你可能感兴趣的:(ACM)