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:8 3: 2 7 10 1: 4 2: 5 3 1: 4 1: 3 1: 4 4: 6 8 1 5 1: 4Sample Output:
3 4 3 1
题目描述:
1.给定 n 个人的兴趣爱好 ,
2.一行代表一个人,
3.给出的数字依此代表:爱好个数k,k个爱好的编号
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 1001
using 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;
}