1107 Social Clusters

题目来源:PAT (Advanced Level) Practice

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

words:

Clusters 集群,群集        register 登记,注册        potential 潜在的        network 网

题意:

给出n个人的爱好列表(爱好用1-1000的数字表示),具有相同爱好的人认为是一个集群,而且,若A和B是一个集群,B和C是一个集群,那么则A、B、C是一个集群;求出集群的个数和每个集群的人数;因此使用并查集来处理;

思路:

1. 使用一个hobby[1001]数组记录第一个开始喜欢该爱好的人,若还没有人喜欢该爱好,则为0;

2. 使用一个ab[N+1]数组表示并查集,即将相同爱好的人连接在一起 ;ab[i]初始默认为i,及每个人最开始都是独立的;

3. 输入每个人的爱好;每输入一个人的爱好,若该爱好尚无人喜欢,则将该人记录其中若已经有人喜欢,则判断这两个人(正在输入的人和第一个喜欢该爱好的人)是否属于同一集群,即是否根相同;若不相同则合并

4. 使用集合se来统计ab[]中根的个数,即集群的个数

5. 遍历集合se中的所有元素(即根),统计每个根下的结点数(包括根),即每个集群的人数;

6. 输出集群的个数以及按照降序输出每个集群的人数

//PAT ad 1107 Social Clusters
#include <iostream>
using namespace std;
#include <set>
#include <vector>
#include <algorithm> 
#define N 1000

int hobby[1000+1];	//记录第一个开始喜欢该爱好的人,若还没有人喜欢该爱好,则为0 
int ab[N+1];	//0号元素不用,将相同爱好的人连接在一起 

int find(int x)		//查找x的根 
{
	if(x==ab[x])
		return x;
	return ab[x]=find(ab[x]);
}

int main()
{
	int n,i;
	cin>>n;
	char c;
	int k,x;
	for(i=1;i<=n;i++)		//输入 
	{
		cin>>k>>c;	//爱好个数 
		ab[i]=i;	//初始指向自己 
		while(k--)
		{
			cin>>x;		//第i个人的爱好 
			if(hobby[x]==0)	//该爱好尚无人喜欢 
				hobby[x]=i;
			else
			{
				int fa=find(hobby[x]);	//寻找喜欢爱好x的第一个人的根; 
				int fb=find(i);		//寻找i的根,或 fb=i; 
				if(fa!=fb)			//有不同的根,则合并 
				{
					ab[fa]=fb;		//将fa指向fb 
				}
			}					
		}
	}
	
	set<int> se;
	for(i=1;i<=n;i++)	//统计所有的根 
	{
		x=find(i);
		se.insert(x);
	}
	
	cout<<se.size()<<endl;	//the total number of clusters,即根的个数 
	vector<int> ans;
	for(auto w:se)	//统计每个根下的结点的数(包括根) 
	{
		int c=0;
		for(i=1;i<=n;i++)
			if(ab[i]==w)
				c++;
		ans.push_back(c);		//the numbers of people in the clusters 
	}
	sort(ans.begin(),ans.end());
	for(i=ans.size()-1;i>0;i--)	//输出 
		cout<<ans[i]<<" ";
	cout<<ans[i]<<endl;
			
	return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值