并查集 POJ 1611

题目点这里

题目大意

学校中有很多社团,有的学生同时加了不同的社团,现在有一种病会传染,假设一个社团里有一个人有被传染的嫌疑,那么该社团的所有人都会被传染。
初始条件:0号学生有嫌疑,算出所有有嫌疑的学生总数。

题解

将每组输入的学生编号使用并查集联系起来,然后找出0号元素的祖先,输出个数。此处用一个辅助sum数组来统计属于本节点的元素个数,所以最后输出sum[find(id[0])]即为所求。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
const int M = 30005;
int id[M];
int sum[M];
int find(int p)
{
    while(p != id[p])   p = id[p];
    return p;
}
//bool connected(int p,int q)
//{
//  return find(p) == find(q);
//}
void unionn(int p,int q)
{
    int pRoot = find(p);
    int qRoot = find(q);
    if(pRoot != qRoot)
    {
        id[qRoot] = pRoot; //q->p 
        sum[pRoot] += sum[qRoot];
    }
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m))
    {
//      int count = 0;
        /*if(m == 0)
        {
            printf("1\n");
            continue;
        }*/
        if(n == 0 && m == 0)
            break;
        for(int i = 0;i < n; i++) //初始化 
        {
            id[i] = i;
            sum[i] = 1;
        }
        for(int i = 0;i < m;i++)
        {
            int t;
            int p,q;
            scanf("%d",&t);
            scanf("%d",&p);
            for(int j = 1;j < t;j++)
            {
                scanf("%d",&q);
                unionn(p,q);   //依次相连,从后往前 
                p = q; 
            }
        }
        /*for(int i = 0; i < n;i++)
        {
            if(find(i) == id[0])
                ++count;
        }*/
        int x = find(id[0]);
        printf("%d\n",sum[x]);          
    }
    return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值