L3-003. 社交集群
时间限制
1000 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
在社交网络平台注册时,用户通常会输入自己的兴趣爱好,以便找到和自己兴趣相投的朋友。有部分兴趣相同的人们就形成了“社交集群”。现请你编写程序,找出所有的集群。
输入格式:
输入的第一行给出正整数N(<=1000),即社交网络中的用户总数(则用户从1到N编号)。随后N行,每行按下列格式列出每个人的兴趣爱好:
Ki: hi[1] hi[2] ... hi[Ki]
其中Ki(>0)是第i个人的兴趣的数量,hi[j]是第i个人的第j项兴趣的编号,编号范围为[1, 1000]内的整数。
输出格式:
首先在第一行输出整个网络中集群的数量,然后在第二行按非递增的顺序输出每个集群中用户的数量。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:8 3: 2 7 10 1: 4 2: 5 3 1: 4 1: 3 1: 4 4: 6 8 1 5 1: 4输出样例:
3 4 3 1
并查集
开始做的时候 是把人并起来,这样子比较难判断,因为比如 第一个 1 2 3 ,第二个 4 5 ,第三个 3 5,操作第三个的时候,第二个就不好操作了。后来想到把集群并起来,然后再来判断人,这样就简单很多。还是上面的例子 ,第一个 归到 1,第二个归到 4,第三个 取根 3(1),5(4),1<4 所以归到了1。当然,为了把4也归到1,每次输入的结尾还要遍历一下。
这个思路相当于就是把 小集群弄成大集群,这样可以一一对应比较舒服
代码:
#include<iostream>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
int num[1010]={0};
int tre[1010]={0};
int check[1010]={0};
int find(int n){
while(n!=num[n])
n=num[n];
return n;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=1000;i++)
num[i] = i;
for(int i=1;i<=n;i++){
int k,tmp;
scanf("%d",&k);
getchar();
vector<int> v;
int in=9999;//min,找最小的
for(int j=0;j<k;j++){
scanf("%d",&tmp);
v.push_back(tmp);
in = min(in,find(num[tmp]));
}
for(int j=0;j<k;j++)//把集群 归并到最小的
num[find(v[j])]= in;
tre[i] = in;//tre[i] 指第i人 归属的集群
}
int sum=0;
for(int i=1;i<=n;i++){
if(!check[find(tre[i])]){
sum++;
check[find(tre[i])] = 1;
}
else check[find(tre[i])]++;
}
sort(check,check+1001);
cout<<sum<<endl;
int cnt=0;
for(int i=1000;i>=0;i--){
if(check[i]==0) continue;
else {
cnt++;
cnt == 1? printf("%d",check[i]):printf(" %d",check[i]);
}
}
cout<<endl;
}