【并查集】:poj1611,The Suspects

来源:互联网 发布:不同域名指向同一ip 编辑:程序博客网 时间:2024/05/21 17:58

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 30003struct 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 30005struct 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;}


1 0
原创粉丝点击