标签:
http://poj.org/problem?id=1611
题目大意:
有一个学校,有N个学生,编号为0-N-1,现在0号学生感染了非典,凡是和0在一个社团的人就会感染,并且这些人如果还参加了别的社团,他所在的社团照样全部感染,求感染的人数。
解题思路:
并查集的变种,实质就是求0所在的强连通图的结点数目。
这道题纠结在数据的输入上,他只是告诉你哪些学生是同一个社团的。这就需要处理一下,我的想法是:如果这个社团有num个孩子,new出一个大小为num的数组,第一个孩子不处理,从第二个孩子起,和上个孩子合并,这样就完成了他们的合并。
AC代码:
#include<iostream> #include<cstdio> using namespace std; int p[30005],b[30005],r[30005],num[30005]; int n,m,k; int Find(int x) { if(p[x]!=x) p[x]=Find(p[x]); return p[x]; } void Union(int x,int y) { //x=Find(x); //y=Find(y); if(x==y) return; if(r[x]>r[y]) { p[y]=x; num[x]+=num[y]; } else { p[x]=y; if(r[x]==r[y]); r[y]++; num[y]+=num[x]; } } int main() { while(scanf("%d%d",&n,&m)&&(m+n)) { for(int i=0; i<n; i++) { p[i]=i; r[i]=0; num[i]=1; } while(m--) { scanf("%d",&k); for(int i=1; i<=k; i++) scanf("%d",&b[i]); for(int i=1; i<k; i++) { int x=Find(b[i]); int y=Find(b[i+1]); Union(x,y); } } int p=Find(0); printf("%d\n",num[p]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/a-clown/p/5918019.html