并查集 - 1611 The Suspects

题目地址: http://poj.org/problem?id=1611

分析: 

  - 数据结构

    - parent[x] 表示 x 元素的父节点位置.

    - rank[x] 记录x的子链的长度, 以便在合并的时候减少链条长度. 查找的时候使用了路劲压缩, 所以两个节点的rank差不会大于1, 所以提高的效率也不是很大, 但还是很有帮助.

    - quantity[x] 表示x的子节点的个数(包含自身). 对于根节点来说, 就是这个集合的大小.

  - build(n) 由于规模 n 在变化, 所以需要多大的规模就只初始化那一部分即可. 

  - findx(x) 找到x所在集合的根节点的编号, 并且将路径压缩至1(每个节点直接指向父节点)

  - mergexy(x,y) 按照rank大小合并, 并且更新quantity和rank

  - 下面的代码中, 如果将  while(m-- && scanf("%d",&k)==1)  改为:  while(scanf("%d",&k)==1 && m--) 则会出现错误, 因为当m == 0  的时候本来没有group, k应该没有, 但是还是scanf将下一组的数据输入了,  所以会造成TLE.

  - 代码如下:

#include <stdio.h>

#define MAXNUM 30100

//parent[i]记录i号节点对应的父节点编号. 它们属于同一个集合.
int parent[MAXNUM];
//quantity[i]记录指向i或者i的子节点的节点个数.对于根节点即集合大小(指向自身).
int quantity[MAXNUM];
//rank[i] 记录i的深度, 以便建立一棵平衡的树.
int rank[MAXNUM];

void build(int n){
    for(int i=0;i<n;i++){
        parent[i] = i;
        rank[i] = 0;
        quantity[i] = 1;
    }
}

// 找到x所在的集合的根节点.并压缩路径
int findx(int x){
    int r = x;
    int t;
    while(parent[r] != r){
        r = parent[r];
    }
    //将r的所有间接子节点直接指向r本身, 压缩了路径.
    while(r != x && parent[x] != x){
        t = parent[x];
        parent[x] = r;
        x = t;
    }
    return x;
}

// 将x,y所在的集合合并
void mergexy(int x, int y){
    int rootx = findx(x);
    int rooty = findx(y);
    if (rootx == rooty)
        return;
    // 根据秩的大小合并
    if(rank[rootx] > rank[rooty]){
        parent[rooty] = rootx;
        quantity[rootx] += quantity[rooty];
    }else if(rank[rootx] == rank[rooty]){
        parent[rootx] = rooty;
        quantity[rooty] += quantity[rootx];
        rank[rooty]++;
    }else{
        parent[rootx] = rooty;
        quantity[rooty] += quantity[rootx];
    }
}

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m) && (n || m)){
        //初始化数据结构
        build(n);
        int k,x,y;
        while(m-- && scanf("%d",&k)==1){
            scanf("%d",&x);
            for(int i=1;i<k;++i){
                scanf("%d",&y);
                mergexy(x,y);
            }
        }
        printf("%d\n",quantity[findx(0)]);
    }
    return 0;
}
posted @ 2015-10-05 00:56  roger9567  阅读(135)  评论(0编辑  收藏  举报