1. 程式人生 > >並查集加記錄個數

並查集加記錄個數

poj1611

輸入n個學生

m個集合,每個集合前有一個數為k,為集合元素個數 

每個集合的第一號為傳染源,和它在一個集合 中的都為感染者,輸出感染人數

#include<stdio.h>
#define MAX 30005

int a[MAX],pre[MAX];

int find(int x)
{
    if(x!=pre[x])

        //找到其祖先節點
        pre[x] = find(pre[x]);

    //由父節點繼續向上遞迴查詢 ,並將其父節點變成找到的
    return pre[x];
}
void merge(int x,int y)
{
    //分別查詢兩點的祖先節點。
    int prex = find(x);
    int prey = find(y);

    //如果二者的祖先節點不一致,那麼任意讓二者中某一個認另一個為祖先,保證同集合。

    if(prex == prey)
    {
        return ;
    }
    //應該是祖先節點進行組合。而不是當前節點!
    pre[prey] = prex;
    a[prex] += a[prey];//順序是因為0號是預設每行的根節點;
}
int main()
{
    int n,m;
    int k,x,y;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
        {
            return 0;
        }
        for(int i=0;i<n;i++)
        {
            //先將自身作為祖先節點。
            pre[i] = i;
            a[i] = 1;//長度預設為1
        }
        for(int i=0;i<m;i++)
        {
            //給出集合每個集合人數,以及第一個人的編號
            scanf("%d%d",&k,&x);//x是每個集合中的傳染源;
            k--;
            while(k--)
            {
                scanf("%d",&y);
                merge(x,y);//每一行的x即第一個就是傳染源即根節點;
            }
        }
        printf("%d\n",a[find(0)]);//是a[find(0)]因為每一行根節點不定,a[0]可能還有根節點;這是為了找出它的最根節點

    }
    return 0;
}