您的位置:首页 > 其它

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

2016-11-30 18:52 555 查看
  题意:有n个人,每个人有k个爱好,如果两个人有某个爱好相同,他们就处于同一个集合。问总共有多少个集合,以及每个集合有多少人,并按从大到小输出。

  很明显,采用并查集。vis[k]标记爱好k第一次出现的人的编号,如果为0则表示未出现。

  当前第i个人若也存在爱好k,则只要将i与vis[k]两个人合并即可。

最后father[i]相同的即处在同一个集合中。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cmath>
using namespace std;
/*
并查集
*/
const int maxn=1005;
int vis[maxn]; //vis[i]标记某爱好第一次出现在第几个人,0表示还未出现。
int n;

struct UF{
int father[maxn];
void init(){
for(int i=0;i<maxn;i++){
father[i]=i;
}
}
int find_root(int x){
if(father[x]!=x){
father[x]=find_root(father[x]);
}
return father[x];
}
void Union(int x,int y){
int fx=find_root(x);
int fy=find_root(y);
if(fx!=fy){
father[fy]=fx;
}
}
}uf;

bool cmp(int a,int b){
return a>b;
}
int main()
{
char str[20];
int num,a;
scanf("%d",&n);
memset(vis,-1,sizeof(vis));
uf.init();
for(int i=1;i<=n;i++){
scanf("%s",str);
int len=strlen(str);
str[len-1]='\0';
num=atoi(str);
for(int k=0;k<num;k++){
scanf("%d",&a);
if(vis[a]==-1)
vis[a]=i;
else{
uf.Union(vis[a],i); //若已出现过,则第i个人与第vis[a]个人合并,即分为一组
}
}
}
int cnt[n+1];
int res=0;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++){
int idx=uf.find_root(i);
if(cnt[idx]==0)
res++;
cnt[idx]++;
}
sort(cnt+1,cnt+n+1,cmp);
printf("%d\n",res);
for(int i=1;i<res;i++)
printf("%d ",cnt[i]);
printf("%d",cnt[res]);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: