并查集+欧拉回路

来源:互联网 发布:小约翰 震惊 知乎 编辑:程序博客网 时间:2024/05/16 08:45





运用并查集+欧拉回路 白书P112+P200
1.得到根节点。
 2.合并出入字母形成同一棵树,如题e->m->a,e为根节点应该只有一个,从e进m出,从m进a出,如此循环。
3.初始化父亲们
4.欧拉回路中,最多只有两个点出入度不相等,并且必须是一个点出度恰好比入度大1,另一个的入度比出度大1
5.更新父亲树!
6.ans用来存入度和出度不相等的点,j累计
7.if后接continue语句!


#include <stdio.h>

#include <math.h>
#include<string.h>
#define M 30
int vis[M],father[M],in[M],out[M],ans[M];
char str[1010];

int getfather(int x)
{
    if(father[x]!=x)
        father[x]=getfather(father[x]);
    return father[x];
}

void combine(int a,int b)
{
    int x,y;
    x=getfather(a);
    y=getfather(b);
    if(x!=y)
        father[x]=y;
}

int main()
{
    int T,n,a,b,count,i,j;
    scanf("%d",&T);
    while(T--)
    {
        count=0;
        memset(vis,0,sizeof(vis));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        scanf("%d",&n);
        for(i=0;i<26;i++)
            father[i]=i;

        for(i=0;i<n;i++)
        {
            scanf("%s",str);
            a=str[0]-'a';
            b=str[strlen(str)-1]-'a';
            combine(a,b);
            in[b]++;
            out[a]++;
            vis[a]=1;
            vis[b]=1;
        }
        for(i=0;i<26;i++)
            father[i]=getfather(i);


        for(i=0;i<26;i++)
            if(vis[i]&&father[i]==i)
                count++;

            if(count>1)
            {
                printf("The door cannot be opened.\n");
                continue;
            }

        j=0;
        for(i=0;i<26;i++)
            if(vis[i]&&out[i]!=in[i])
                ans[j++]=i;

        if(j==0)
        {
            printf("Ordering is possible.\n");
            continue;
        }
        else if(j==2&&((out[ans[0]]-in[ans[0]]==1&&in[ans[j-1]]-out[ans[j-1]]==1)||(out[ans[j-1]]-in[ans[j-1]]==1&&in[ans[0]]-out[ans[0]]==1)))
        {
            printf("Ordering is possible.\n");
            continue;
        }
        printf("The door cannot be opened.\n");

    }

    return 0;

}



http://blog.csdn.net/dm_vincent/article/details/7655764

0 0
原创粉丝点击