朋友圈(并查集)
题目
某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。
输入
输入的第一行包含两个正整数N(<=30000)和M(<=1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:第i个俱乐部的人数Mi(空格)学生1(空格)学生2…学生Mi
输出
输出给出一个整数,表示在最大朋友圈中有多少人。
样例
题解
(强烈安利并查集详解(超级简单有趣~~就学会了) 对并查集的解释有趣简单,非常适合新手理解,题目中具体的并查集构建过程可以参考链接中的说明,在此不再赘述)
这是一道简单的并查集模版题,每个俱乐部可以看成是一棵树,俱乐部里的学生就是树的节点,我们只需要把不同的俱乐部通过同样的学生成员关联起来(相当于连接两棵树)即可。
代码
#include <stdio.h>
#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;
}