• 并查集


    题目地址: 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
    ",quantity[findx(0)]);
        }
        return 0;
    }
    
  • 相关阅读:
    XtraBackup2.3.3安装配置使用(innobakupex)
    MySQL主从配置问题整理
    saltstack之(十二)配置管理mount
    常用HTTP状态码和CURL 000问题
    RHEL6解决无法使用YUM源问题
    zabbix监控MySQL
    ELK-Python(三)
    解决eclipse项目下出现deployment descriptor和jax-ws web services
    【未来畅想】未来的电信通讯行业,账号密码将取代sim卡
    最新samba.tar.gz安装方法
  • 原文地址:https://www.cnblogs.com/roger9567/p/4855249.html
Copyright © 2020-2023  润新知