POJ 1703

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

压缩路径的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;

}

 

你可能感兴趣的:(poj)