POJ 1611(并查集)
题目:多组输入,先输入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; } }