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;
    }
  • 相关阅读:
    SCI写作经典替换词,瞬间高大上!(转)
    最佳化常用测试函数 Optimization Test functions
    算法复杂度速查表
    VS 代码行统计
    CPLEX IDE 菜单栏语言设置( 中文 英文 韩文 等多国语言 设置)
    如何从PDF文件中提取矢量图
    Matlab无法打开M文件的错误( Undefined function or method 'uiopen' for input arguments of type 'char)
    visual studio 资源视图 空白 解决方案
    MFC DialogBar 按钮灰色不响应
    嗨翻C语言笔记(二)
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367091.html
Copyright © 2011-2022 走看看