并查集小题目

152 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

微信朋友圈出了扩大版。其中好友分为直接好友和间接好友。和你有直接好友关系的是你的直接好友,你的直接好友的好友都是你的间接好友。所有互为好友的人共同构成了一个朋友圈,圆里每个人都其他人的直接成间接的好友。
已知微信用户共有N位,以及他们之间的直接好友关系,请你找出总共形成了多少个扩大版朋友圈。

输入格式

第一行输入两个整数N(K<=NK=IDDD),MO<=M<IDDD),分别表示微信用户的人数、他们之间的直接好友关系的数目。 接下来有M行输入,每行输入两个整数xK=X<=N)、y(<=y<=N),表示用户X和用户y是直接好友。

分析

比较常见的算法题,利用并查集。并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STU 10000
char g[MAX_STU][MAX_STU];
int father[MAX_STU];
//查找当前元素所在树的根节点(代表元素)
int find(int x){
    if(x == father[x])
        return x;
    return find(father[x]);
}
//合并元素x, y所处的集合
void Unite(int x, int y){ //查找到x,y的根节点
    x = find(x);
    y = find(y);
    if(x == y)
    return ;
    //将x的根节点与y的根节点相连
    father[x] = y;
}
int main()
{
    memset(g,0,sizeof(g));

    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<=n;i++){
        father[i]=i;
    }
    int a1,a2;
    for(int i=0;i<m;i++){
        scanf("%d %d",&a1,&a2);
        if(a1>a2){
            int tmp=a1;
            a2=a1;a1=tmp;
        }
        father[a2]=a1;
    }
    for(int i=1;i<=n;i++){
        int f=find(i);
        father[i]=f;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(father[i]==i) ans++;
    }
    printf("%d\r\n",ans);
    return 0;
}