POJ1611

在并查集合并节点时,合并操作直接作用在当前节点的根结点上,和当前节点基本无关.

下面是AC代码: 

#include<iostream>
#include<cstring>
using namespace std;
const int maxn=30005;
int n,m,k;
int num[maxn];//num储存当前节点的编号
int pre[maxn];
int ans;//保留传染源的编号
int vis[maxn];//标志当前节点是不是传染原,0表示是
int cnt;
void make_set()
{
    for(int i=0; i<n; i++)
    {
        pre[i]=i;
    }
}
int finds(int x)
{
    if(x!=pre[x])
        pre[x]=finds(pre[x]);
    return pre[x];
}
void unions(int x,int y)
{//合并时和当前节点无关,直接操作根节点
    int root1=finds(x);
    int root2=finds(y);
    if(root1!=root2)
        pre[root2]=root1;
}
int main()
{
    while(cin>>n>>m)
    {
        if(n==0)
            break;
        cnt=1;
        memset(vis,0,sizeof(vis));
        make_set();
        vis[0]=1;
        ///ans=0;
        for(int mm=0; mm<m; mm++)
        {
            cin>>k;
            cin>>num[0];
            for(int i=1; i<k; i++)
            {
                cin>>num[i];
                unions(num[0],num[i]);
                ///cout<<num[0]<<"和"<<num[i]<<"节点合并为"<<finds(num[0])<<endl;
            }
        }
        for(int i=1; i<=n-1; i++)
            if(finds(i)==finds(0))
                cnt++;
        cout<<cnt<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41658955/article/details/81352990