您的位置:首页 > 其它

PAT 1107. Social Clusters (30) 特殊问题+并查集+数量信息并查集

2017-09-16 17:35 501 查看
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string.h>
#include<cmath>

using namespace std;

//37min
//耗时于思考和编码
/*************************
题意:
每个人有k个习惯
只要有相同习惯的人就会被分到一个群组中。

【即若3号有A和B习惯,4号有B和C习惯
则3和4号被分到同一组
若5号有C和D习惯
5号也会加入3和4号那一组。】
求有多少个群组,并按从大到小输出群组中成员数量
*************************/

/************************
求解要点:
1.很显然,群组合并,此为并查集。
2.连接点为习惯,人只是作为数量1加入群组信息中。
3.当1号有习惯ABCD时,直接选A的father做根节点bf,len[bf]++
并分别求出BCD3个习惯的father,把len都加上去,再连接到根节点bf上
4.注意getfather时,用递归,并且时刻更新每个点的father为最新father。
************************/

/***********************
笔记:
memset放在<string.h>中
*********************/
#define M 120000
#define INF 0xffffff

int father[M];
int len[M];

//查
;int getfather(int p)
{
int fa;
if(father[p]==p)
return p;
fa=getfather(father[p]);
father[p]=fa;
return fa;
}

int main()
{
int n,p;
int m,hobby,bigfather,sum;
int k,i,j,child;
scanf("%d",&n);
for(i=0;i<M;i++)
{
father[i]=i;
len[i]=0;
}
for(i=0;i<n;i++)
{
scanf("%d:",&m);
scanf("%d",&hobby);

//选第一个习惯的根节点为新集合的根节点
bigfather=getfather(hobby);
father[hobby]=bigfather;

sum=len[bigfather]+1;
for(j=1;j<m;j++)
{
scanf("%d",&hobby);
p=getfather(hobby);
//合
sum+=len[p];
father[p]=bigfather;
len[p]=0;
}
len[bigfather]=sum;
}

vector<int> ans;
for(i=0;i<M;i++)
{
if(len[i]!=0)
{
ans.push_back(len[i]);
}
}
printf("%d\n",ans.size());
sort(ans.begin(),ans.end());
printf("%d",ans[ans.size()-1]);
for(i=ans.size()-2;i>=0;i--)
printf(" %d",ans[i]);
cout<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: