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;
    }
  • 相关阅读:
    Java.io.outputstream.PrintStream:打印流
    Codeforces 732F. Tourist Reform (Tarjan缩点)
    退役了
    POJ 3281 Dining (最大流)
    Light oj 1233
    Light oj 1125
    HDU 5521 Meeting (最短路)
    Light oj 1095
    Light oj 1044
    HDU 3549 Flow Problem (dinic模版 && isap模版)
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367091.html
Copyright © 2011-2022 走看看