http://poj.org/problem?id=1611
题目大意:
有一个学校,有N个学生,编号为0-N-1,现在0号学生感染了非典,凡是和0在一个社团的人就会感染,并且这些人如果还参加了别的社团,他所在的社团照样全部感染,求感染的人数。
注意,并查集Find操作:
不进行路径压缩:return Find(a[i].parent)
进行路径压缩:a[i].parent=Find(a[i].parent); return a[i].parent; 不要用while循环!!!
# include<iostream> using namespace std; # define N 30003 struct STUDENT { int parent; int size; }; STUDENT student[N]; void MakeUnionFind(int n) { for(int i=0;i<n;i++) { student[i].parent=i; student[i].size=1; } } int FindParent(int i) { /* while(student[i].parent!=i) { student[i].parent=FindParent(student[i].parent); } return student[i].parent; */ if(student[i].parent==i) { return i; } else { //return FindParent(student[i].parent); no path compression //do path compression, 注意,不能使用上面的循环!!! student[i].parent=FindParent(student[i].parent); return student[i].parent; } } void Union(int i, int j) { int ip=FindParent(i); int jp=FindParent(j); if(ip!=jp) { if(student[ip].size<student[jp].size) { student[ip].parent=jp; student[jp].size+=student[ip].size; } else { student[jp].parent=ip; student[ip].size+=student[jp].size; } } } int main() { int n,m,k; int i,j,t1,t2; while(true) { cin>>n>>m; if(n==0 && m==0) { break; } MakeUnionFind(n); for(i=1;i<=m;i++) { cin>>k>>t1; for(j=2;j<=k;j++) { cin>>t2; Union(t1,t2); } } cout<<student[student[0].parent].size<<endl; } return 0; }
注意下面的错误:
for(i=1;i<=m;i++) { cin>>k>>t; //不应该把这个放到外面,因为在之后的union过程中,t的parent可能会改变 //tp=FindParent(t); for(j=2;j<=k;j++) { cin>>tt; tp=FindParent(t); ttp=FindParent(tt); if(tp!=ttp) { Union(tp,ttp); } } }
# include<iostream> using namespace std; # define N 30005 struct NODE { int p,s; }; NODE node[N]; void MakeSet(int n) { for(int i=0;i<=n;i++) //start from "0" { node[i].p=i; node[i].s=1; } } int FindParent(int t) { if(t==node[t].p) { return t; } else { int tp=node[t].p; node[t].p=FindParent(tp); return node[t].p; } } void Union(int tp, int ttp) { if(node[tp].s<node[ttp].s) { node[tp].p=ttp; node[ttp].s+=node[tp].s; } else { node[ttp].p=tp; node[tp].s+=node[ttp].s; } } int main() { int n,m,k,i,j,t,tt,tp,ttp; while(true) { cin>>n>>m; if(n==0 && m==0) { break; } MakeSet(n); for(i=1;i<=m;i++) { cin>>k>>t; //不应该把这个放到外面,因为在之后的union过程中,t的parent可能会改变 //tp=FindParent(t); for(j=2;j<=k;j++) { cin>>tt; tp=FindParent(t); ttp=FindParent(tt); if(tp!=ttp) { Union(tp,ttp); } } } cout<<node[FindParent(0)].s<<endl; } return 0; }