【并查集】poj 1703 Find them, Catch them(二集合问题)

题目描述:

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

 

中文大意:

城市中存在着两个帮派,警察需要根据获得的信息,判断抓捕的两个帮派分子是否属于同一帮派。

D [a] [b] 语句,表示 a 和 b 属于不同的帮派,

A [a] [b] 语句,是在询问 a 和 b 是否属于同一个帮派。

 

思路:

我们规定:若 i 属于集合 A ,则 i+n 属于集合 B。

两个帮派可以抽象为两个集合,x 和 y 是两名帮派分子。

因为 x 和 y 属于不同的集合,所以 x 和 y+n 属于同一集合,y 和 x+n 属于同一集合。

判断 x 和 y 是否属于同一集合,只需判断二者所属集的根节点是否相同。

若 root[x] = root[y],则说明二者在一个集合中,

若 root[x] = root[y+n],则说明二者在不同集合中,

若以上两种情况都不满足,则说明二者所属情况还不确定。

 

代码:

#include<iostream>
using namespace std;

int sets[200002];//各节点的所属集 
int height[200002];

//初始化,每个节点属于独立的集合 
void init(int n){
    for(int i=1;i<=n;i++){
        sets[i] = i;
        height[i] = 1;
    }
}

//查询节点 x 的所属集 
int find(int x){
    //寻找根节点 
    int root = x;
    while(root != sets[root]){
        root = sets[root];
    }
    
    //路径压缩:将路径上各节点的所属集修改为根节点 
    int i = x;
    while(sets[i] != root){
        int j = sets[i];
        sets[i] = root;
        i = j;
    }
    return root;
}

//合并 
void union_set(int x, int y){
    //寻找节点 x 的所属集 
    x = find(x);
    //寻找节点 y 的所属集 
    y = find(y);
    
    //若两个节点的所属集树高相同,则将 x 的所属集并到 y 的所属集
    if(height[x] == height[y]){
        sets[x] = y;
        height[y]++;
    }//否则,将矮树并到高树,高树的树高保持不变 
    else if(height[x] > height[y]){
        sets[y] = x;
    }
    else{
        sets[x] = y;
    }
}

int main(){
    int t,n,m;
    scanf("%d", &t);
    while(t--){
        scanf("%d %d", &n, &m);
        //集合 1:1 ~ n
        //集合 2:n+1 ~ 2*n 
        init(2*n);
        
        char c;
        int x,y;
        for(int i=0;i<m;i++){
            getchar();
            scanf("%c %d %d", &c, &x, &y);
            
            if(c == 'A'){
                if(find(x) == find(y)){
                    printf("In the same gang.\n");
                }
                else if(find(x) == find(y+n)){
                    printf("In different gangs.\n");
                }
                else{
                    printf("Not sure yet.\n");
                }
            }
            else if(c == 'D'){
                //规定:如果 i 属于帮派 A,那么 i+n 属于帮派 B 
                union_set(x, y+n);
                union_set(y, x+n);
            }
        }
    }
}

 

posted @ 2021-03-04 18:59  狂奔的小学生  阅读(165)  评论(0编辑  收藏  举报