7-12 朋友圈 (25 分)

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

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

第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi

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

输入样例:
7 4
3 1 2 3
2 1 4
3 5 6 7
1 6
输出样例:
4
该题使用了并查集的思想,可以把并查集理解成各个门派比武,刚开始的时候,每个人自成一个门派,然后进行比武,比武的方式是让各门派的门主来进行PK,输了的一方(门主)并到赢了的一方(门主)的门下,而输了的门主的徒弟也顺着师傅进入到另一个门主门下

#include <stdio.h>
typedef struct {
    int cnt;
    int parent;
}node;
int find(node *f,int u)//这里的f可以比作天下,f[i]表示这天下中的一个人,他有可能是某门派的门主,也有可能是徒弟。再输入一个人,找到他的师傅
{
    while(f[u].parent!=u)//师傅是特殊的,师傅表示我自学成才,师傅的师傅还是自己,即父节点还是自己,自己指向自己
        u=f[u].parent;//如果输入的这个人不是师傅,那么就顺着这个人往上找,找到其师傅为止
    return u;
}
int max(node *f,int n)//输入一个填写下,再输入该天下的人数,找到这个天下中带领弟子最多的人即师傅,返回他带了几个徒弟
{
    int m=-1;
    for(int i=1;i<=n;i++)
    {
        if(m<f[i].cnt)
        {
            m=f[i].cnt;
        }
    }
    return m;
}
int main()
{
    int m,n,count;
    scanf("%d%d",&n,&m);
    node f[n+1];
    for(int i=1;i<=n;i++)
    {
        f[i].cnt=1;//刚开始时每个人的门派只要一个人,即自己
        f[i].parent=i;//刚开始各门派的门主的师傅都是自己
    }
    for(int i=0;i<m;i++)
    {
        scanf("%d",&count);
        int u,U;
        scanf("%d",&u);
        U=find(f,u);//先找到最开始这个人的师傅,第一次循环时,这个人的师傅就是自己,等到之后就可能不是了
        for(int i=2;i<=count;i++)
        {
            int v,V;
            scanf("%d",&v);//输入第二个人...
            V=find(f,v);//找到他的师傅
            if(U!=V)//如果两个人的师傅不是同一个人,就开始合并
            {
                f[V].parent=U;//这里就直接默认U获胜,V成为了徒弟
                f[U].cnt=f[U].cnt+f[V].cnt;//接下来U带领的徒弟就是两个师傅带领徒弟的总和
            }
        }
    }
    printf("%d",max(f,n));
    return 0;
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值