1107 Social Clusters

题目大意

有n个人,每个人喜欢k个活动,如果两个人有任意一个活动相同,就称为他们处于同一个社交网络。求这n个人一共形成了多少个社交网络。

思路解析

可将爱好看做边,人看做顶点。所以本题问的就是极大联通子图的个数,与各联通子图内顶点的数量。由于本题并没有给出顶点的信息,而是各条边的信息。所以必然要用并查集统计连通图的个数。
所谓并查集,简单地说就是,把一群节点分成若干个集合,每个集合内部都是联通的,但集合之间不连通,判断两个节点是否属于一个集合的充要条件是,两个节点分别至少存在一条路径,可以到达同一个节点。
放到本题的背景下,给出一个人的爱好,通过他的爱好,不断将这个人归属到不同圈子,在归属新圈子的同时,老圈子和他一起归属到新圈子之下,于是两个圈子变成了一个大圈子;如此循环下去,让你找出最终剩下的圈子。

示例代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> father;
int find_root(int v) {
	int a = v;
	while (v != father[v]) {
		v = father[v];
	}
	while (a != father[a]) {//优化树形结构
		int z = a;
		father[z] = v;
		a = father[a];
	}
	return v;
}
void Union(int x, int y) {
	int x_root = find_root(x);
	int y_root = find_root(y);
	if (x_root != y_root) {
		father[x_root] = y_root;
	}
}
bool cmp(int a, int b) {
	return a > b;
}
int main() {
	int n;
	scanf("%d", &n);
	father.resize(n + 1);
	vector<int> isfount(1010);
	for (int i = 1; i <= n; i++) {
		father[i] = i;
	}
	for (int i = 1; i <= n; i++) {
		int num, temp;
		scanf("%d: ", &num);
		for (int j = 0; j < num; j++) {
			scanf("%d", &temp);
			if (isfount[temp] == 0) {
				isfount[temp] = i;
			}
			Union(i, isfount[temp]);
		}
	}
	vector<int> roots(n + 1);
	for (int i = 1; i <= n; i++) {
		roots[find_root(i)]++;
	}
	int cnt = 0;
	for (int i = 1; i <= n; i++) {
		if (roots[i] != 0) {
			cnt++;
		}
	}
	sort(roots.begin(), roots.end(), cmp);
	printf("%d\n%d", cnt, roots[0]);
	for (int i = 1; i < cnt; i++) {
		printf(" %d", roots[i]);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值