zoukankan      html  css  js  c++  java
  • POJ.1611 The Suspects (并查集)

     POJ.1611 The Suspects (并查集)

    题意分析

    对于每组测试数据:
    这个学校有n个人,m小组,依次给出m个小组的信息,每行一个小组。
    每个小组的信息包括,k,表示有k个人,k个数字,分别是这k个人的ID。
    现在ID为0的人感染了病毒,他及他的小组成员全部会感染病毒,每个小组成员都会感染自己所在小组的成员(每个成员可以加入多个小组)。问现在总共有多少个人感染了病毒?
    比较裸的并查集。
    我们可以把每个人看作是一个集合,对于一个小组的成员,就是不停地在做并集操作。并集的时候,同时要合并他们下面的节点个数。最后只要找到0的根是谁,输出其下的节点个数即可。

    代码总览

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <sstream>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <cmath>
    #define INF 0x3f3f3f3f
    #define nmax 30005
    #define MEM(x) memset(x,0,sizeof(x))
    using namespace std;
    int father[nmax];
    int rnk[nmax];//秩
    int num[nmax];//爸爸下节点的个数,集合中元素个数
    void makeset(int x)
    {
        father[x] = x;//自己是自己的爸爸
        rnk[x] = 0;//秩为0
        num[x] = 1;//爸爸下面元素个数为1
    }
    int findset(int x)
    {
        int r = x,temp;
        while(father[r] != r) r = father[r];// 一直向上找
        //压缩路径
        while(r != x){
            temp = father[x];//暂存爸爸
            father[x] = r;//直接把爸爸改成根
            x = temp;//向上
        }
        return r;
    }
    void unionset(int x, int y)
    {
        x = findset(x);
        y = findset(y);
        if(x == y) return;// 根相同 不用合并
        if(rnk[x] > rnk[y]){
            father[y] = x; // 小的并到大的上
            num[x]+=num[y];
        }else{
            father[x] = y;
            if(rnk[x] == rnk[y])
                rnk[x]++;
            num[y]+=num[x];
        }
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int n,m;
        while(scanf("%d %d",&n,&m)){
            if(n == 0 && m == 0) break;
            if(m == 0){
                printf("1
    ");
                continue;
            }
            for(int i = 0; i<n;++i) makeset(i);//每个人自己是一个set
            for(int j = 0; j<m;++j){
                int num,first,temp; scanf("%d",&num);
                for(int k = 0; k<num;k++){
                    if(!k) scanf("%d",&first);
                    else{
                        scanf("%d",&temp);
                        unionset(first,temp);
                    }
                }
            }
            int rt = findset(0);
            printf("%d
    ",num[rt]);
        }
        return 0;
    }
  • 相关阅读:
    图片文件重命名
    MySql基础学习-Sql约束
    MySql基础学习-库表操作
    java内存模型
    数据库常用函数整理
    linux用户管理
    Db2数据库在Linux下的安装和配置
    图像金字塔
    特征值与特征向量
    齐次线性方程组
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367091.html
Copyright © 2011-2022 走看看