• 【并查集】poj 1611 The Suspects


    题目描述:

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

     

    中文大意:

    SARS 是一种传播性极强的感染病,为了最大程度地控制其传播,最好的策略是将嫌疑人与其他人分开。

    在大学中,有很多学生团体,一个学生可以加入多个团体。

    规定:一旦团体中的某个成员成为可疑对象,则该团体中的所有成员都将成为可疑对象。

    要求:统计可疑对象的数量。

    思路:

    一个学生团体就是一个集合。

    我们可以让团体内所有同学,都与第一个同学 x 合并。

    若某位同学 y 还属于别的集合(pre[y] != y),则将这两个集合合并。

    最终,同学 0 所在集合的节点数即为可疑对象数量。

     

    代码:

    #include<iostream>
    using namespace std;
    
    int n,m;
    int pre[30000];//各节点的所属集 
    int height[30000];//各集合的高度 
    
    //初始化,每个节点属于独立的集合 
    void init(){
        for(int i=0;i<n;i++){
            pre[i] = i;
            height[i] = 1;
        }
    }
    
    //查询节点 x 的所属集 
    int find(int x){
        //寻找根节点 
        int root = x;
        while(root != pre[root]){
            root = pre[root];
        }
        
        //路径压缩:将路径上节点的所属集修改为根节点 
        int i = x;
        while(pre[i] != root){
            int j = pre[i];
            pre[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]){
            pre[x] = y;
            height[y]++;
        }//否则,将矮树并到高树,并且高树的高度保持不变 
        else if(height[x] > height[y]){
            pre[y] = x;
        }
        else{
            pre[x] = y;
        }
    }
    
    int main(){
        while(scanf("%d %d", &n, &m) && (n||m)){
            init();
            
            int k, x, y;
            for(int i=0;i<m;i++){
                scanf("%d %d", &k, &x);
                //k 个数属于同一个集合,用第一个数与其他数字进行合并 
                for(int j=1;j<k;j++){
                    scanf("%d", &y);
                    union_set(x, y);
                }
            }
            
            //统计 0 所在集合的节点数 
            int root0 = find(0);
            int num = 1;
            for(int i=1;i<n;i++){
                int root = find(i);
                if(root == root0){
                    num++;
                }
            }
            printf("%d
    ", num);
        }
    } 
    作者:老干妈就泡面
    本文版权归作者和博客园共有,欢迎转载,但请给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    centos7grub2 引导win10
    必测的支付漏洞(一)——使用fiddler篡改支付金额
    使用Fiddler进行IOS APP的HTTP抓包
    Fiddler实现手机抓包——小白入门
    信息收集工具recon-ng详细使用教程
    Chrome浏览器扩展开发系列之一:初识Google Chrome扩展
    Dear Project Manager, I Hate You
    敏捷中的沟通与故事点
    项目经理与敏捷开发
    C#中使用反射获取结构体实例
  • 原文地址:https://www.cnblogs.com/bjxqmy/p/14479989.html
Copyright © 2020-2023  润新知