7-90 社交集群 (30分)
当你在社交网络平台注册时,一般总是被要求填写你的个人兴趣爱好,以便找到具有相同兴趣爱好的潜在的朋友。一个“社交集群”是指部分兴趣爱好相同的人的集合。你需要找出所有的社交集群。
输出格式:
首先在一行中输出不同的社交集群的个数。随后第二行按非增序输出每个集群中的人数。数字间以一个空格分隔,行末不得有多余空格。
输入样例:
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;
int p[1009], user[1009], hobby[1009];
int find(int x){ //找祖先
if(p[x] == x){
return x;
}
return p[x] = find(p[x]);
}
void merge(int x, int y){ //合并
int xx = find(x), yy = find(y);
if(xx != yy){
p[yy] = xx;
}
}
bool cmp(int x, int y){ //因为题目说非曾序,所以两个数相等时不用交换顺序
return x > y;
}
int main()
{
for(int i=1; i<=1000; i++){
p[i] = i;
}
int n,k,h,num=0;
char ch;
cin >> n;
for(int i=1; i<=n; i++){
cin >> k >> ch >> user[i]; //user[i]:用第一个兴趣来代表每一个人
for(int j=1; j<=k-1; j++){
cin >> h;
merge(user[i], h);
}
}
for(int i=1; i<=n; i++){
hobby[find(user[i])]++; //计算每个圈子多少人
}
for(int i=1; i<=1000; i++){
if(hobby[i]!=0) num++; //统计圈子个数
}
sort(hobby, hobby+1001, cmp);
cout << num << endl;
for(int i=0; i<num; i++){
if(i!=0) cout << " ";
cout << hobby[i];
}
return 0;
}