您的位置:首页 > 其它

【并查集】:poj1611,The Suspects

2015-12-02 21:35 423 查看
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
;

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
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息