PAT A1107 Social Clusters (30分)
程序员文章站
2022-03-13 22:05:50
...
前言
正文
参考题解
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
/*
题意:社交簇,有共同爱好的人在一个团体(A和B有共同爱好,B和C有共同爱好,则ABC都在同一个团体),
给出n个人各自有哪些爱好,总共有多少个团体,并且按照团体中的人数降序排序
思路:一眼看过去应该是并查集,仔细一看题目给的是每个人的爱好,本题使用
并查集应该是要以人的编号为元素的,因此需要做爱好与人编号的映射,故设置
数组hobby,用hobby[i]=j表示用户j的爱好是i。这样findFather(hobby[i])就表示是j
的father。
*/
const int N=1e3+10;
int father[N],hobby[N],cluster[N];//cluster[i]表示以i为父节点的社交簇中有多少人
int findFather(int x){//带路径压缩
if(father[x]!=x)father[x]=findFather(father[x]);
return father[x];
}
//合并
void Union(int a,int b){
int fa=findFather(a);
int fb=findFather(b);
if(fa!=fb){
father[fa]=fb;
}
}
bool cmp(int a,int b){//降序排序
return a>b;
}
int main(){
int n;
cin>>n;
//初始化
for(int i=1;i<=n;i++){
father[i]=i;
cluster[i]=0;
}
for(int i=1,k;i<=n;i++){
scanf("%d: ",&k);
for(int j=0,ki;j<k;j++){
scanf("%d",&ki);
if(hobby[ki]==0){//ki爱好首次出现,记录该用户i
hobby[ki]=i;
}
//若后面再次出现ki,那么将本用户i和第一次出现ki时表示的用户hobby[ki],这两个用户合并
Union(i,findFather(hobby[ki]));
}
}
for(int i=1;i<=n;i++){
//注意此处需要写成cluster[findFather[i]]
//不能写成cluster[father[i]],否则会有测试点通不过
cluster[findFather(i)]++;//记录每个团体的人数
}
int cnt=0;//团体的个数
for(int i=1;i<=n;i++){
if(cluster[i]!=0){
cnt++;
}
}
cout<<cnt<<endl;
sort(cluster+1,cluster+1+n,cmp);
for(int i=1;i<=cnt;i++){
if(i!=1)printf(" ");
printf("%d",cluster[i]);
}
return 0;
}
上一篇: ORB特征检测
下一篇: LeetCode 178. 分数排名