PAT

Nothing to fear


种一棵树最好的时间是十年前,其次是现在!

那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~


人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!

Social Clusters

考点: 并查集

题目大意

给定n个人,接下来 n 行输入每一个人的爱好。爱好的编号在 [1 , 1000]之间,人的编号爷在[1 , n]之间,具有相同爱好的人可以构成一个社交圈。

输出一共存在多少个社交圈子,打印出每一个圈子之中的人数。

分析

这道题意图明显就是想让我们使用并查集,但是并查集合并的条件是具有相同爱好的人合并在一起,我们首先需要将具有相同爱好的人存在一起。然后遍历每一个爱好将其中每一个人所属的集合进行合并,最后统计人数和个数进行排序即可。注意每个人最初指向的是自己。

需要注意的点:

完整代码

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 10005;
int f[N] , n , ans[N];
vector<int> hobby[N];
bool cmp(int a,int b)
{
	return a > b;
}
int find(int k)
{
	if(k == f[k])return k;
	else return find(f[k]);
}
void Union(int a,int b)
{
	int A = find(a) , B = find(b);
	f[A] = B; 
}
int main()
{
	for(int i = 1;i < N;i ++)f[i] = i;
	cin >> n;char ch;
	for(int i = 1; i <= n;i ++)
	{
		int k = 0 , x;cin >> k >> ch;
		for(int j = 0;j < k ;j ++)
		{
			cin >> x;
			hobby[x].push_back(i);
		}
	}
	for(int i = 0;i < N;i ++)
	{
		if(hobby[i].size() == 0)continue;
		for(int j = 0;j < hobby[i].size() - 1;j ++)
		{
			int a = hobby[i][j] , b = hobby[i][j + 1];
			Union(a , b);
		}	
	}
	int cnt = 0;
	for(int i = 1;i <= n;i ++)
	{
		//printf("f[%d] = %d
", i ,f[i]);
		if(i == find(i))cnt++;
		ans[find(i)]++;
	}
	cout << cnt << endl;
	sort(ans , ans + N, cmp);
	for(int i = 0;i < cnt;i ++)
	{
		if(i == 0)printf("%d", ans[i]);
		else printf(" %d",ans[i]);
	}
	return 0;	
}
原文地址:https://www.cnblogs.com/wlw-x/p/13345967.html