大致题意:
n个学生分属m个团体,(0 < n <= 30000 ,0 <= m <= 500) 一个学生可以属于多个团体。一个学生疑似患病,则它所属的整个团体都疑似患病。已知:0号学生疑似患病,以及每个团体都由哪些学生构成,求一共有多少个学生疑似患病。
思路分析:
并查集的一个简单应用,利用并查集确定某一集合或者团体有多少元素(或个体)。在并查集板子的基础上再开一个total数组,用来记录当前某个集合有多少个元素,实时更新这个数组的值即可。
只需要在Merge(合并)函数上做一些修改:
void Merge(int a,int b){
int p1=GetParent(a);
int p2=GetParent(b);
if(p1==p2) return;
total[p1]+=total[p2]; //合并时修改total数组的值
parent[p2]=p1;
}
贴代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define PI acos(-1.0)
#define seed 31//131,1313
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MAX=30010;
int n,m,k;
int parent[MAX];
int total[MAX];
int GetParent(int a){
if(parent[a]!=a)
parent[a]=GetParent(parent[a]);
return parent[a];
}
void Merge(int a,int b){
int p1=GetParent(a);
int p2=GetParent(b);
if(p1==p2) return;
total[p1]+=total[p2];
parent[p2]=p1;
}
void Read(){
for(int i=0;i<m;i++){
scanf("%d",&k);
int x,y;
scanf("%d",&x);
for(int j=1;j<k;j++){
scanf("%d",&y);
Merge(x,y);
}
}
}
void Init(){
for(int i=0;i<n;i++){
parent[i]=i;
total[i]=1;
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
if(n==0&&m==0) break;
Init();
Read();
printf("%d\n",total[GetParent(0)]);
}
return 0;
}