并查集-按秩合并

1239: 中山学院 ACM小组

Time Limit: 1 Sec   Memory Limit: 64 MB
Submit: 79   Solved: 21
[ Submit][ Status][ Web Board]

Description

经过几年的发展,中山学院 ACM队伍越来越庞大,水平越来越高,影响力也越来越大。随着人员数量的壮大,为了营造一个良好的队内之间沟通讨论氛围,教练组决定让队员之间以小组的形式进行讨论。而教练组又希望所有认识的人都在同一组里面讨论,以提高大家的积极性。而这里的认识可以是直接认识或是间接认识(如果A和 B认识,B 和 C认识,这时A和C可以通过B从而使三个人成为同一个小组的成员。四个人以上的做类似的处理。),假如有一个人他谁都不认识,那么没办法了,他只能自己呆在角落发呆了。当然,他自己也算一个讨论组。同时每个队员都有一个唯一的编号,编号从0 到 n-1(n是队员总数)。现在队伍里面有n个人,跟m组关系,每组关系有两个数a,b,表示a跟b相互认识。那么现在问你,我们学校ACM队伍里面一共组成了多少个讨论组?并且对于每个队员,你是否知道他所属讨论组的人数有多少?

Input

对于每组输入,第一行为两个数n 和 m, (1 <=n <=100,1 <=m<=100),分别代表ACM队内的总人数n和m组关系。接下来的m行,每行有两个数 a 和b,a 和b 是队员的编号,表示 a 和 b认识(0 <= a,b<=n-1)。下面一行输入一个整数k,代表有k组询问,后面的k行每行输入一整数 x,表示此次询问编号为x 的队员所属小组的人数。 (n 和m同时为0时输入结束)

Output

第一行输出讨论小组的数目(格式为”X groups in Zsc_Acmer Camp”,其中X表示讨论小组数目)后面的k行,每一行输出对应询问的回答。

Sample Input

5 30 11 20 2501234

Sample Output

3 groups in Zsc_Acmer Camp33311
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int d[500],s[500];
int find(int x)
{
    int k,j,r;
    r=x;
    while(r!=d[r])
        r=d[r];
    k=x;
    while(k!=r)
    {
        j=d[k];
        d[k]=r;
        k=j;
    }
    return r;
}
void unio(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y)
        return ;
    if(s[x]>=s[y])
    {
        d[y]=x;
        s[x]+=s[y];
    }
    else
    {
        d[x]=y;
        s[y]+=s[x];
    }
}
int main()
{
    int n,m,a,b,ki,tt;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
            break;
        for(int i=0;i<n;i++)
        {
            d[i]=i;
            s[i]=1;
        }
        while(m--)
        {
            scanf("%d%d",&a,&b);
            unio(a,b);
        }
        int cas=0;
        for(int i=0;i<n;i++)
        {
            if(d[i]==i)
                cas++;
        }
        printf("%d groups in Zsc_Acmer Camp\n",cas);
        scanf("%d",&ki);
        while(ki--)
        {
            scanf("%d",&tt);
            int aa=find(tt);
            printf("%d\n",s[aa]);
        }
    }
    return 0;
}

你可能感兴趣的:(并查集-按秩合并)