天梯赛练习题 L3-003 社交集群 (简单并查集)
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;
}