POJ--1611经典并查集

    地址:http://poj.org/problem?id=1611

     题意:n,m。n个人,编号0-n-1,m个组合:第一个数表示本集合个数,后面是成员。一个成员可以在多个集合里。0号是病人,跟她一个组合的全是病人,问一共有多少人患病。

     解析:直接并查集基本模板,加入一个vis[]数组来记录与本节点相连的树的元素个数。最后输出vis[0]即可。vis[i]=1的一个初始化记得加。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=3e4+10;
int pr[maxn];
int vis[maxn];
int sum=0;
int n,m;
int find(int x){
    while(x!=pr[x])
    {
    //    pr[x]=pr[pr[x]];
        x=pr[x];
    }
    return x;
}
void join(int x1,int x2)
{
    int f1=find(x1),f2=find(x2);
    if(f1!=f2)
    {
        pr[f1]=f2;
        vis[f2]+=vis[f1];
    }
    return ;
}
void first()
{
    for(int i=0;i<=n;i++)
    {
        pr[i]=i;
        vis[i]=1;
    }
}
int main()
{
    while(scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
            break;
        first();
        int mid;
        while(m--)
        {
            int nn,x;
            scanf("%d",&nn);
            scanf("%d",&mid);
            for(int i=2;i<=nn;i++)
            {
                scanf("%d",&x);
                join(x,mid);
            }
        }
        cout<<vis[find(0)]<<endl;
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/12525695.html