POJ 1703 Find them, Catch them(并查集)

http://poj.org/problem?id=1703

题意 :有两个黑帮团伙。有n个团伙成员,现在并不知道他们分别属于哪个团伙。给你一些信息,信息中包含两个人的编号,表示这两个人分属不同团伙,然后给你两个人的编号,问你他们俩是不是属于同一个团伙。

思路 : 并查集。因为这个题给出的每个关系都代表着两个人属于不同的团伙,所以没办法像普通的并查集那样,只用两个集合就行,例如,给你(1,2)(5,6)(1,5),根据关系我们可以知道2,5属于一个团伙,1,6属于一个团伙,但是你并没有办法表示。书上介绍了一种常用的做法:只要两者关系确定了,就将他们放入同一集合中,再另外增加一个关系数组father[]来表示该结点与其父亲的关系,0表示是同一类,1表示是不同团伙,初始时集合只有自己一个元素,所以father的初始值置为1。

#include<iostream>

#include<string.h>

#include<stdio.h>

#include<stdlib.h>



using namespace std;



int pre[100010];//代表着父亲结点,如果D后边是a b,则pre[b]=a ;

int father[100010] ;//代表着这个点和父亲结点的关系,是属于同一类还是不同团伙

int m,n ;



int find(int x)

{

    int temp = pre[x] ;

    if (pre[x] == x)

    return x ;

    pre[x] = find(pre[x]);

    father[x] = father[x] == father[temp] ? 0 : 1 ;//等于0表示属于同一类

    return pre[x];

}



void unionn(int x,int y,int xx,int yy)

{

    pre[xx] = yy ;

    father[xx] = father[x] == father[y] ? 1 : 0 ;

}

int main()

{

    int t ;

    scanf("%d",&t) ;

    int m,n ;

    while(t--)

    {

        scanf("%d %d",&n,&m) ;

        for(int i = 1 ; i <= n ; i++)

          {

              pre[i]=i;

              father[i] = 0 ;

          }

        char x ;

        int a,b ;

        for(int i = 1 ; i <= m ; i++)

        {

            scanf("\n%c %d %d",&x,&a,&b) ;

           int aa = find(a),bb = find(b);

            if(x == 'D')

            {

                if(aa != bb)

                unionn(a,b,aa,bb) ;

            }

            if(x == 'A')

            {

                if(aa != bb)//父亲不同,说明此时还没有建立关系

                {

                    printf("Not sure yet.\n");

                    continue ;

                }

                if(father[a] == father[b])//父亲相同,在比较两者和父亲的关系

                {

                    printf("In the same gang.\n") ;

                    continue ;

                }

                printf("In different gangs.\n");

                continue ;

            }

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(catch)