导航

POJ 1703

Posted on 2015-04-11 09:05  tun~  阅读(167)  评论(0编辑  收藏  举报

种类并查集,基本思想是每次压缩路径都必须同时更新子节点和根节点的关系,这种关系是通过子节点和父亲节点的关系,以及父亲节点与根节点的关系运算出来。

压缩路径的findme();参考了大神的代码,做的第二个种类并查集....

#include<stdio.h>
#include<string.h>
int cri[100005];//记录每一个元素的根节点
int pp[100005];//记录元素与根节点的关系,0代表盟友,1代表敌人
int findme(int a)
{
    if(a==cri[a])
    {
        return a;
    }
    int temp=cri[a];//temp用于记录递归前该节点的父亲节点
    cri[a]=findme(cri[a]);//找到a节点的根节点
    pp[a]=(pp[temp]+pp[a])&1;//通过a节点的父亲节点与根节点的关系以及a节点和其父亲节点的关系更新得到a节点和新的根节点的关系
    return cri[a];
}
void link(int a, int b)
{
    int ttmp,tmpa,tmpb;
    tmpa=findme(a);
    tmpb=findme(b);
    if(tmpa!=tmpb)
    {
        cri[tmpb]=tmpa;
        pp[tmpb]=(pp[a]+pp[b]+1)&1;
    }
}
int main()
{
    int t,n,m,a,b;
    char ca;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(pp,0,sizeof(pp));
        for(int i=1;i<=n;i++)
        {
            cri[i]=i;
        }
        getchar();
        for(int i=0;i<m;i++)
        {
            ca=getchar();
            if(ca=='D')
            {
                scanf("%d%d",&a,&b);
                getchar();
                if(a==b)
                    continue;
                link(a,b);
            }
            else
            {
                scanf("%d%d",&a,&b);
                getchar();
                if(findme(a)==findme(b))
                {
                    if((pp[a]+pp[b])&1)
                    {
                        printf("In different gangs.\n");
                    }
                    else
                    {
                        printf("In the same gang.\n");
                    }
                }
                else
                {
                    printf("Not sure yet.\n");
                }
            }
        }
    }
    return 0;
}