您的位置:首页 > 其它

GPLT L2-007. 家庭房产【并查集】

2017-03-13 21:57 330 查看
题目:家庭房产

思路:利用并查集分类家族即可。

开始存储每个人的房数和面积时我用了一个结构体,然后下标为当前人的编号,最后用findd函数寻找到各自的家族的根后加入家族的存储对应值即可。

还有是用一个标记数组将预先输入的编号标记,这样在查找家族数时就可以排除那些压根没有的值了!

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10000;
int n,f[maxn+5];
struct family{
int houses,area;
}val[maxn];
struct whl{
int id,persons;
double hs,aas;
}ans[maxn];
int visit[maxn+5];
bool cmp(whl x,whl y){//排序
if(x.aas == y.aas) return x.id < y.id;
return x.aas > y.aas;
}
void init(){//初始化
for(int i=0;i<=maxn;i++) f[i] = i;
memset(visit,0,sizeof(visit));
memset(val,0,sizeof(val));
}
int findd(int v){//寻找根节点
if(v != f[v]) f[v] = findd(f[v]);
return f[v];
}
void mergee(int u,int v){//合并
int fu = findd(u),fv = findd(v);
if(fu != fv) f[fv] = fu;
}
int main()
{
int id[1005],far,mou,k,child;
while(~scanf("%d",&n)){
init();//初始化
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&id[i],&far,&mou,&k);
visit[id[i]] = 1;//标记出现的编号
if(far != -1) {mergee(id[i],far);visit[far] = 1;}//家族合并
if(mou != -1) {mergee(id[i],mou);visit[mou] = 1;}//家族合并
for(int j=0;j<k;j++){
scanf("%d",&child);
visit[child] = 1;//标记出现编号
mergee(id[i],child);//家族合并
}
scanf("%d%d",&val[id[i]].houses,&val[id[i]].area);//将每组的房数和面积存入对应本组的第一个人的编号
}
int cnt = 0;
for(int i=0;i<=maxn;i++)//扫一遍编号,将没有改变的值存入,即根节点
if(visit[i] && f[i] == i) ans[cnt++].id = i;
//开始进行家族的人数,房数,面积的计算
for(int i=0;i<cnt;i++){
int record = 999999,num = 0;
for(int j=0;j<=maxn;j++)
if(visit[j] && findd(j) == ans[i].id){//将于先前的根节点比较,当查找的编号的父节点于当前的父节点相等即为同一家族
num++;//累计家族人数
ans[i].hs += val[j].houses;//累计房数
ans[i].aas += val[j].area;//累计面积
record = min(record,j);//记录家族中最小编号
}
ans[i].id = record;//更新家族最小编号
ans[i].aas /= (double)num;//计算平均面积
ans[i].hs /= (double)num;//计算平均房数
ans[i].persons = num;//保存人数
}
sort(ans,ans+cnt,cmp);//按要求排序
printf("%d\n",cnt);
for(int i=0;i<cnt;i++) printf("%04d %d %.3lf %.3lf\n",ans[i].id,ans[i].persons,ans[i].hs,ans[i].aas);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  PAT 解题思路 acm