POJ ~ 1611 ~ The Suspects (并查集)

题意:非典开始扩散,有许多学生团体。同一组的学生经常彼此相通,一个学生可以同时加入几个小组。为了防止非典的传播,
一旦一组中有一个可能的患者, 组内的所有成员就都是可能的患者,我们需要把可能的患者都隔离。
多组输入输出
第一行为两个整数n和m, 其中n是学生的数量, m是团体的数量。0 < n <= 30000,0 <= m <= 500。
每个学生编号是一个0到n-1之间的整数,一开始只有0号学生是患者。
下面M行,每一行有一个整数k,代表成员数量。之后,有k个整数代表这个群体的学生。一行中的所有整数由至少一个空格隔开。

n = m = 0表示输入结束,不需要处理。每组数据输出需要隔离的人数。

思路:并查集,合并的时候往编号小的上合并。最后判断有多少个以0为根的就是答案。

//#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN = 30005;
int n, m, f[MAXN];
void init()
{
    for (int i = 0; i <= n; i++) f[i] = i;
}
int Find(int x)
{
    if (f[x] == x) return x;
    f[x] = Find(f[x]);
    return f[x];
}
void Union(int a, int b)
{
    int root1 = Find(a), root2 = Find(b);
    f[max(root1, root2)] = f[min(root1, root2)];//编号大的合并到编号小的上
}
int main()
{
    while (~scanf("%d%d", &n, &m) && (n + m))
    {
        init();
        while (m--)
        {
            int k, t1, t2;
            scanf("%d%d", &k, &t1);
            k--;
            while (k--)
            {
                scanf("%d", &t2);
                Union(t1, t2);
            }
        }
        int ans = 0;
        for (int i = 0; i < n; i++)
        {
            if (Find(i) == 0) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}
/*
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0
*/




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值