并查集的具体例题

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
#include
#include
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;
}






你可能感兴趣的:(并查集,最小生成树)