天梯赛练习题 L3-003 社交集群 (简单并查集)

发布时间 2023-03-23 21:56:09作者: 高尔赛凡尔娟

https://pintia.cn/problem-sets/994805046380707840/exam/problems/994805053141925888

题目大意:

当你在社交网络平台注册时,一般总是被要求填写你的个人兴趣爱好,以便找到具有相同兴趣爱好的潜在的朋友。一个“社交集群”是指部分兴趣爱好相同的人的集合。你需要找出所有的社交集群。

输入格式:
输入在第一行给出一个正整数 N(≤1000),为社交网络平台注册的所有用户的人数。于是这些人从 1 到 N 编号。随后 N 行,每行按以下格式给出一个人的兴趣爱好列表:

Ki: hi[1] hi[2] ... hi[Ki]

其中(Ki>0)是兴趣爱好的个数,hi[j]是第j个兴趣爱好的编号,为区间 [1, 1000] 内的整数。

输出格式:
首先在一行中输出不同的社交集群的个数。随后第二行按非增序输出每个集群中的人数。数字间以一个空格分隔,行末不得有多余空格。
输入样例:
8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4
输出样例:
3
4 3 1
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18,MINN=-MAXN;
const LL N=2e6+10,M=4004;
const LL mod=100000007;
const double PI=3.1415926535;
#define endl '\n'
LL a[N];
LL father[N];
void init()
{
    for(int i=1;i<=1000;i++)
    {
        father[i]=i;
    }
}
LL find(LL x)
{
    if(father[x]!=x) father[x]=find(father[x]);
    return father[x];
}
int main()
{
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    int T=1;
    //cin>>T;
    while(T--)
    {
        init();
        LL n;
        scanf("%ld",&n);
        for(int i=1;i<=n;i++)
        {
            LL op;
            scanf("%ld:%ld",&op,&a[i]);
            LL x=a[i];//标记第一个兴趣爱好
            for(int j=2;j<=op;j++)
            {
                LL y;
                scanf("%ld",&y);
                //和第一个兴趣爱好进行合并
                LL fx=find(x),fy=find(y);
                if(fx!=fy)
                {
                    father[max(fx,fy)]=min(fx,fy);
                }
            }
        }
        //从1-n个人中标记相同根(兴趣爱好)的人数
        map<LL,LL> mp;
        for(int i=1;i<=n;i++)
        {
            LL fai=find(a[i]);
            mp[fai]++;
        }
        vector<LL> v;
        for(int i=1;i<=1000;i++)
        {
            //出现过的才需要寻找,没出现过的不需要
            if(mp[i]!=0)
            {
                v.push_back(mp[i]);
            }
        }
        sort(v.begin(),v.end());
        reverse(v.begin(),v.end());
        LL flag=v.size();
        printf("%ld\n",flag);
        for(int i=0;i<v.size();i++)
        {
            if(i==v.size()-1) printf("%ld",v[i]);
            else printf("%ld ",v[i]);
        }
    }
    return 0;
}