PAT——1107 Social Clusters 甲级(并查集)

题目

https://pintia.cn/problem-sets/994805342720868352/problems/994805361586847744

题意

给出n个学生各自的爱好,拥有相同爱好的同时视为在同一个社交网络中。本题需要求出社交网络总数,并按降序输出每个社交网络的人数

代码解析

find和combine都是并查集的老朋友了,不太了解的同学可以在CSDN上自学一下并查集。其中find函数的代码是和参考文章不同的,我采用了递归形式的路径压缩(return fa[x]=find(fa[x]);),不太明白的同学可以看一下我的这篇文章——PTA——哥尼斯堡的“七桥问题(出现运行超时?不妨进来看看)

在判断两个同学是喜欢同样的活动时,采用course数组。course[t]表示喜欢t的第一位同学,如果为0表示之前没有人喜欢t活动。之所以只记录第一个同学,是因为后面所有喜欢t活动的同学都会放入course[t]对应的同学所在的集合中,反正最终大家都是一个集合的,就不需要一直更新course[t]了

isRoot存放每个集合的同学数,因为每个集合中的同学最终都会通过find找到根节点。值为0表示不是根节点,反之是且值为对应的同学数。

最终按要求排序输出即可

AC代码

#include<bits/stdc++.h>
using namespace std;
vector<int> fa,isRoot;
int find(int x)
{
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
void combine(int x,int y)
{
	int a=find(x),b=find(y);
	if(a!=b)
		fa[a]=b;
}
int main()
{
	int n,k,t,cnt=0,course[1001]={0};
	cin>>n;
	fa.resize(n+1);
	isRoot.resize(n+1);
	for(int i=1;i<=n;i++)
		fa[i]=i;
	for(int i=1;i<=n;i++)
	{
		scanf("%d:",&k);
		while(k--)
		{
			cin>>t;
			if(course[t]==0)
				course[t]=i;
			combine(i,course[t]);	
		}	
	}
	for(int i=1;i<=n;i++)
		isRoot[find(i)]++;
	for(int i=1;i<=n;i++)
		if(isRoot[i])
			cnt++;
	cout<<cnt<<endl;
	sort(isRoot.begin(),isRoot.end(),greater<int>());
	for(int i=0;i<cnt;i++)
	{
		if(i) cout<<" ";
		cout<<isRoot[i];	
	}	
}

参考

1107. Social Clusters (30)-PAT甲级真题

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值