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;
}