A1107社交圈(并查集)

题意

输入n个人的爱好,爱好相同的在同一个社交圈,跟书上的好朋友一样,如果A、B都喜欢活动1,B、C都喜欢活动2,A和B在同一圈,B和C在同一圈,则A和C也在同一圈。

思路:

跟书上一样,书上直接给出朋友关系,本题需要先依靠hobby[]来判断是否在同一个集合,还有就是书上是直接用bool数组判断是根节点的个数,本题更进一步,需要求出每个集合中的元素个数。

AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1100;
int father[N]; //存放父亲结点 
int hobby[N]={0};   //hobby[h]为任何一个喜欢活动h的人的编号 
int isRoot[N]={0};   
int findFather(int x){  //查找x所在集合的根结点 
	if(x==father[x]) return x;
	else return findFather(father[x]);
}
void Union(int a,int b){  //合并a和b所在的集合 
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB){
		father[faA]=faB;
	}
}
int cmp(int a,int b){
	return a>b;
}
void init(int n){  //初始化集合father[i]=i,且flag[i]=false 
	for(int i=1;i<=n;i++){
		father[i]=i;
	}
}
int main(){
	int n,k,h;
	scanf("%d",&n);  //人数 
	init(n);  //初始化 
	for(int i=1;i<=n;i++){
		scanf("%d:",&k);   //第i个人喜欢的活动个数k 
		for(int j=0;j<k;j++){
			scanf("%d",&h);   //输入第i个人喜欢的活动h 
			if(hobby[h]==0){  //如果活动h第一次有人喜欢 
				hobby[h]=i;    //令i喜欢h ,hobby[i]=i,father[i]=i,所以hobby[h]=i=father[i]即为活动h的根节点 
			}
			Union(i,findFather(hobby[h]));     //合并i跟hobby[h]的集合 
		}
	}
	for(int i=1;i<=n;i++){
		isRoot[findFather(i)]++;  //i的根节点是findFather(i),人数+1 
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		if(isRoot[i]!=0) ans++;
	}
	printf("%d\n",ans);
	sort(isRoot+1,isRoot+1+n,cmp);
	for(int i=1;i<=ans;i++){
		printf("%d",isRoot[i]);
		if(i<ans) printf(" ");
	}
	return 0;
}

tips:
其实hobby[h]=i那边我不太懂,我个人的理解是把活动h的根节点设定为i。如果有大佬看了觉得我这个理解不对,可以评论一下,感谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值