PAT 1107 Social Clusters [并查集]

本文介绍了一种使用并查集算法解决社交网络中寻找共同兴趣群体的问题。通过输入每个人的爱好列表,算法能够找出所有具有共同爱好的人群集群,并按集群大小递减排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

When register on a social network, you are always asked to specify your hobbies in order to find some potential friends with the same hobbies. A social cluster is a set of people who have some of their hobbies in common. You are supposed to find all the clusters.

Input Specification:

Each input file contains one test case. For each test case, the first line contains a positive integer N (≤1000), the total number of people in a social network. Hence the people are numbered from 1 to N. Then N lines follow, each gives the hobby list of a person in the format:

K​i​​: h​i​​[1] h​i​​[2] ... h​i​​[K​i​​]

where K​i​​ (>0) is the number of hobbies, and h​i​​[j] is the index of the j-th hobby, which is an integer in [1, 1000].

Output Specification:

For each case, print in one line the total number of clusters in the network. Then in the second line, print the numbers of people in the clusters in non-increasing order. The numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4

Sample Output:

3
4 3 1

-----------------------------------这是题目和解题的分割线-----------------------------------

考察并查集的用法,不需要合并爱好,合并人就行了。

#include<cstdio>
#include<algorithm>

using namespace std;

int n,father[1010];

bool cmp(int a,int b)
{
	return a>b;
}

//初始化 
void init(int x)
{
	for(int i=1;i<=n;i++)
		father[i] = i;
}

//寻找x所在集合的根 
int findRoot(int x)
{
	int tmp = x;
	while(x!=father[x]) //找到根结点 
		x = father[x];
	//路径压缩 
	while(tmp!=father[tmp]) //将该路径上所有结点都直接指向根结点x 
	{
		int a = tmp;
		tmp = father[tmp]; //回溯父亲结点 
		father[a] = x; //指向根结点 
	}
	return x; 
}

//合并集合 
void unionS(int a,int b)
{
	int aF = findRoot(a);
	int bF = findRoot(b);
	//如果根不相等,说明不是同一个集合,合并 
	if(aF!=bF) father[aF] = bF;
}

int main()
{
	int k,x,i,j,flag[1010] = {},root[1010] = {},cnt = 0;
	scanf("%d",&n);
	init(n); //初始化,每个人都是一个集合 
	for(i=1;i<=n;i++)
	{
		scanf("%d:",&k);
		for(j=0;j<k;j++)
		{
			scanf("%d",&x);
			//flag[x]用来记录第一次出现x的位置i 
			if(flag[x]==0) flag[x] = i;
			//合并当前位置i和爱好x第一次出现的位置flag[x] 
			unionS(i,findRoot(flag[x]));
		}
	}
	for(i=1;i<=n;i++)
		root[findRoot(i)]++; 
	for(i=1;i<=n;i++)
		if(root[i]) cnt++; //不为空,说明这是一个集合的根 
	sort(root+1,root+1+n,cmp); //排序递减输出 
	printf("%d\n",cnt);
	for(i=1;i<=cnt;i++)
	{
		printf("%d",root[i]);
		if(i!=cnt) printf(" "); //末尾无空格 
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值