当你在社交网络平台注册时,一般总是被要求填写你的个人兴趣爱好,以便找到具有相同兴趣爱好的潜在的朋友。一个“社交集群”是指部分兴趣爱好相同的人的集合。你需要找出所有的社交集群。
输出格式:
首先在一行中输出不同的社交集群的个数。随后第二行按非增序输出每个集群中的人数。数字间以一个空格分隔,行末不得有多余空格。
输入样例:
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
思路
开始把问题想复杂了。其实直接可以:每一个人用第一个兴趣编号作为代表,将一个人的兴趣编号用并查集和并起来,这样有相同兴趣的人就被分在了一个组,然后遍历每一个人,查找他的兴趣的父亲节点,然后用一个计数数组技术便可以得到每个圈子有多少人,不为零的个数就是圈子个数。
上面是另一个博主的思路,我一开始也想的复杂了,也就是没懂题目的意思;
题目的意思:一号有2 3 4兴趣 二号有 1 3 4 兴趣 三号有8 9 2兴趣,也就是并查集,拥有同一种兴趣的属于一个圈子,一号二号三号都是一个圈子的。
本来是刚学并查集,有点没懂上面的思路,就是二号和一号如何能够确认在一个圈子
在union方法中,合并两个兴趣,需要先找到这两个兴趣的祖先结点,再将祖先结点赋值给另一个祖先结点,这样就具有同一个祖先结点,这也是并查集的合并的思想
代码如下::
#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;
}