並查集的具體例題

1217.CD收藏

Description

    lmh平常愛聽歌,所以買了很多的CD來收藏,但是因爲平常整理不當,所以忘記了這些CD的歌手是誰。現在他想知道他到底收藏了多少位歌手的專輯,於是他想了一個辦法,同時拿出兩個CD來聽,可以分辨出來是否爲同一個歌手唱的。(如果沒有說明則認爲是沒有分辨出來,爲不同歌手)現在他列了一個表記錄哪些專輯是同一歌手,但他面對着這一堆記錄不知如何處理,請你告訴他到底他有多少個歌手的專輯。

Input

    第一行n,m。n表示CD的個數(標號分別爲1到n),m表示lmh所分辨出來的共有幾組。接下來的m行每一行有兩個數a,b。表示a唱片和b唱片是同一個歌手。(1<=n,m<=10000)

Output

    總計的歌手數量。

Sample Input

10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4

Sample Output


3


題目的步驟及思路的分析:

首先假設這10個CD都是不同的歌手,用一個一維數組F,用下表來表示這10個CD,用每個下表對應的單元格來存儲每個CD的歌手是誰,所以此刻1號CD就是1號歌手唱的,f[1]爲1,以此類推。


現在進行合併,第一條線索“1號CD和2號CD是同一個歌手唱的”,原來“1號和2號CD的歌手是不同的”,所以將2號CD歸給1號歌手(1號歸給2號也是可以的,但必須規定好靠哪一邊)。所以2號CD就變成了1號歌手的歌,將F[2]改爲1。再依此類推。



已經AC過的代碼:(這是Kruskal算法)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,x,y;
int arr[10005];
int getf(int v)
{
    if(arr[v]==v)
        return v;
    else
    {
        arr[v]=getf(arr[v]);
        return arr[v];
    }
}
int merg(int v,int u)
{
    int t1,t2;
    t1=getf(v);
    t2=getf(u);
    if(t1!=t2)
    {
        arr[t2]=t1;
    }
    return 0;
}

int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int sum=0;
        memset(arr,0,sizeof(arr));
        for(int i=1; i<=n; i++)
        {
            arr[i]=i;
        }
        for(int i=1; i<=m; i++)
        {
            scanf("%d %d",&x,&y);
            merg(x,y);
        }
        for(int i=1; i<=n; i++)
        {
            if(arr[i]==i)
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章