PAT - 甲级 - 1107. Social Clusters (30) (并查集)

来源:互联网 发布:ummy mac 破解 编辑:程序博客网 时间:2024/06/06 01:00

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:

Ki: hi[1] hi[2] ... hi[Ki]

where Ki (>0) is the number of hobbies, and hi[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:
83: 2 7 101: 42: 5 31: 41: 31: 44: 6 8 1 51: 4
Sample Output:
34 3 1

题目描述:

1.给定 n 个人的兴趣爱好 ,

2.一行代表一个人

3.给出的数字依此代表:爱好个数kk个爱好的编号

4.有共同的爱好(只要有一个共同爱好即可)的人组成一个交际圈

题目要求:

1.输出 交际圈的个数  

2.输出每个 交际圈的人数 ,人数按照非升序输出。

题目思路:

求交际圈的个人,同样,只要简单的求出有多少个根节点就可以得出 。

但是 要求每个交际圈有多少人,这里用另外一个数组来记录每个交际圈的人数。


该合并什么:

当然是把人当成集合,来合并人。在比较简单直接的题目中,题目中会直接给出某些人同属于一个集合,给出n个集合,然后让我们写出程序来判断。但是这道题目中,并没有显示的给出没个人分属于哪个集合。而是给出了每个人的爱好。那么合并集合一定是通过爱好来合并的 。

范例分析:

给出了8个人的爱好。我们定义这8个人的编号是1-8号

在3号人中,我们合并3号人和 有爱好5 的人的根节点合并,有爱好3的跟结点合并 ,我们初始化 liked 数组为 0 ,表示没人有这个爱好。

我们可以看到在1号和2号人中,没人有爱好5和爱好3,那么 liked [ 5 ]  , liked [ 3 ] 都是0,我们设定值 为 3;

当我们输入5号人的时候,他的爱好是3,liked [ 3 ] 是 3 ,那么 将 5 和 find( liked [ 3 ] ) 合并集合 。 


这样我们就可以达到人合并的效果 。



如果你不想看上面这么长:看下面:

简单的说:

1.我们定义n个人的编号为 1-n

2.声明一个数组,记录有某爱好的人的编号(用来找根节点)

3.每次合并该人所在集合 与 拥有某爱好的人所在集合 



( ----------  如果 读者有好的想法,欢迎评论 ----------  )




#include<algorithm>#include<cstdio>#include<cstring>#define N 1001using namespace std;int p[N]; //记录结点 int liked[N]; //记录谁有这爱好 int ans[N]; //记录有几组 int find(int x){return p[x] == x ? x : p[x] = find(p[x]);}void join(int x ,int y){int fx = find(x);int fy = find(y);if(fx != fy) p[fx] = fy;}bool cmp(int a,int b){return a>b;}int n,k,a,cnt=0;int main(){//初始化 memset(liked,0,sizeof(liked));memset(ans,0,sizeof(ans));for(int i=0 ;i<N ;i++){p[i] = i; }//输入数据 scanf("%d",&n); for(int i=1 ;i<=n ;i++){ //不能从0开始 , scanf("%d:",&k);for(int j=0 ;j<k ;j++){scanf("%d",&a);if(!liked[a]) liked[a]=i;join(i,find(liked[a]));}} //处理数据 for(int i=1 ;i<=n ;i++){int j = find(i);if(i==j) cnt++;ans[j]++;}sort(ans,ans+n+1,cmp);printf("%d\n",cnt);for(int i=0 ;i<cnt ;i++){printf("%d%c",ans[i] ,i==(cnt-1) ? '\n' : ' ');}return 0;} 





0 0
原创粉丝点击