朋友圈(并查集)

朋友圈(并查集)

题目

某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。

输入

输入的第一行包含两个正整数N(<=30000)和M(<=1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:第i个俱乐部的人数Mi(空格)学生1(空格)学生2…学生Mi

输出

输出给出一个整数,表示在最大朋友圈中有多少人。

样例

朋友圈(并查集)_第1张图片

题解

(强烈安利并查集详解(超级简单有趣~~就学会了) 对并查集的解释有趣简单,非常适合新手理解,题目中具体的并查集构建过程可以参考链接中的说明,在此不再赘述)
这是一道简单的并查集模版题,每个俱乐部可以看成是一棵树,俱乐部里的学生就是树的节点,我们只需要把不同的俱乐部通过同样的学生成员关联起来(相当于连接两棵树)即可。

代码

#include 

#define MAXLEN 30010

int pre[MAXLEN],visit[MAXLEN];

void init(){
    for (int I = 1; I < MAXLEN;i++){
        pre[I] = I;
        visit[I] = 0;
    }
}

int unionsearch(int root){
    int son,temp;
    son = root;
    while (root != pre[root]){ //找到根节点
        root = pre[root];
    }
    While (son != root) { //路径压缩,相当于不断更新节点的父亲节点,直至找到根节点
        temp = pre[son];
        pre[son] = root;
        son = temp;
    }
    return root;
}

Void join(int root1,int root2){ //连接两棵树,让其中一个树的根节点成为另一棵树的根节点的子节点
    int father1,father2;
    father1 = unionsearch(root1);
    father2 = unionsearch(root2);
    if (father1 != father2){
        pre[father2] = father1;
    }
}

int main(){
    int n,m,max;
    int a[MAXLEN];
    max = 0;
    init();
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m;i++){
        int ns;
        scanf("%d", &ns);
        for (int j = 0; j < ns;j++){
            scanf("%d", &a[j]);
            if (j != 0){
                join(a[j-1], a[j]); //构造树
            }
        }
    }
    for (int i = 1; i <= n;i++){ //统计最大的一个集合中节点的数量(相当于统计最大的朋友圈中有多少人)
        int father;
        father = unionsearch(i);
        visit[father]++;
        if (visit[father] > max)
            max = visit[father];
    }
    printf("%d", max);
    return 0;
}

你可能感兴趣的:(数据结构)