POJ 1611(并查集)

POJ1611

题目:多组输入,先输入n个人,后输入m个组。接下来m行每行先输入k,代表这组有k个人,接下来k个数代表这组的成员

编号为0的人可能有病的,和可能有病的人一组的人也会可能有病,输出n个人中有多少人是可能有病的

思路:并查集撸,每组人构成一个集,而他们的头头就是每组输入的第一个人,特判当这组人中存在可能有病的人,就让他们的头头的上司成为0.

最后遍历一下n个人多少人的头头是0.输出即可(头头:Find(x),.上司:pre【x】)

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <vector>
//const int maxn = 1e5+5;
#define ll long long
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}

#define MAX INT_MAX
#define FOR(i,a,b) for( int i = a;i <= b;++i)
#define bug cout<<"--------------"<<endl
using namespace std;
int stu[31000],pre[31000];
int n,m,k,one,two;
int Find(int x)
{
    if(pre[x]==x) return  x;
    return Find(pre[x]);
}
void besame(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy) pre[fy]=fx;
}
void clearr()
{
    for(int i=0;i<n;++i)
        pre[i]=i;
}
int main()
{

    while(1)
    {
        cin>>n>>m;
        if(n==0&&m==0)
            break;
        clearr();
        while(m--)
        {
            cin>>k>>one;
            for(int i=1;i<k;++i)
            {
                cin>>two;
                if(Find(two)==0)
                {
                    besame(0,one);
                }
                else besame(one,two);
            }

        }
        int ans=0;
        FOR(i,0,n-1)
        {
            int hhh=Find(i);
            if(hhh==0)  ans++;
        }
        cout<<ans<<endl;

    }
}

 

posted @ 2019-08-01 01:15  阿斯水生产线  阅读(202)  评论(0编辑  收藏  举报