并查集——社交集群

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

 

在这里插入图片描述

输出格式:
首先在一行中输出不同的社交集群的个数。随后第二行按非增序输出每个集群中的人数。数字间以一个空格分隔,行末不得有多余空格。

输入样例:
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值