Description
题目大意:寻找相同爱好的朋友圈
Input
一个正整数N,代表N个人
接下来N行:Ki hi[1]…hi[n]代表第i个人有k个爱好,爱好下标分别是hi[j] (1<=j<=k)
Output
第一行输出有多少个朋友圈
第二行按照从大到小输出每个朋友圈人数(注意空格)
解题思路
算法标签:并查集
将具有同一爱好的人合并,如果subsets[i].num为0,说明此时爱好I目前还没有人,那么初始化为这个第一个具有此爱好的人,然后与有这个同样爱好的人
最后用count_root统计根节点的个数,个数即为朋友圈个数,再排序输出
代码
//freopen("hao.txt","r",stdin);
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1005;
struct Subset
{
int parent;
int rank;
// 喜欢该活动人的编号
int num;
}subsets[N];
bool cmp(int a,int b)
{
return a>b;
}
int find(int x)
{
if(subsets[x].parent!=x)
subsets[x].parent = find(subsets[x].parent);
return subsets[x].parent;
}
void Union(int x,int y)
{
int x_root = find(x);
int y_root = find(y);
if(x_root==y_root)
return;
if(subsets[x_root].rank < subsets[y_root].rank){
subsets[x_root].parent = y_root;
}
else if(subsets[x_root].rank < subsets[y_root].rank)
subsets[y_root].parent = x_root;
else {
subsets[x_root].parent = y_root;
subsets[y_root].rank++;
}
}
int main()
{
int n = 0,m = 0;
int x =0;
int ans = 0;
int count_root[N] = {0};
cin>>n;
for(int i=1;i<=1000;i++) {
subsets[i].parent = i;
subsets[i].rank = 0;
subsets[i].num = 0;
}
for(int i=1;i<=n;i++) {
cin>>m;
getchar();
for(int j=1;j<=m;j++){
cin>>x;
if(subsets[x].num==0){
subsets[x].num = i;
}
Union(i,find(subsets[x].num));
}
}
for(int i=1;i<=n;i++)
count_root[find(i)]++;
sort(count_root+1,count_root+n+1,cmp);
for(int i=1;i<=n;i++)
if(count_root[i]!=0)
ans++;
cout<<ans<<endl;
for(int i=1;i<=ans;i++){
if(i!=1)
cout<<" "<<count_root[i];
else
cout<<count_root[i];
}
return 0;
}