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

 

posted on 2014-02-11 21:28  枫、  阅读(205)  评论(0编辑  收藏  举报