L2-007. 家庭房产

给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。

输入格式:

输入第一行给出一个正整数N(<=1000),随后N行,每行按下列格式给出一个人的房产:

编号 父 母 k 孩子1 ... 孩子k 房产套数 总面积

其中 编号 是每个人独有的一个4位数的编号; 和  分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0<=k<=5)是该人的子女的个数;孩子i是其子女的编号。

输出格式:

首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:

家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积

其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

做题思路:

1、观察最后两行会发现,2222和2333有相同的孩子——他们的关系没法通过父母的关系网连接到一块;
所以输入孩子也应该连接进关系网中,如果在网中,孩子的父母也指向孩子的根节点;
否则,孩子指向他的该行的父或者母。
2/最后并查集记得进行再次全体进行寻根一次!
3、每次新开一个b【】数组时,记得立即初始化一次!!
4.还出了一个段错误! 您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起!
后来造了一组无厘头的数据:

3
1222 0 23 0 3 300
0 3 -1 0 1 0
3 0 -1 0 1 0

然后程序就炸了,接着仔细想想——搞了半天我没用上并查集的基本操作add()!!

AC程序:(附注释)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<vector>
#include<map>
#define maxn 400000
#define inf 0x3f3f3f3f
using namespace std;
#define N 10018
struct node{
int mo,fa;
int k;//从0开始的
int kids[];
int suit;
int area;
}a[N];
struct family{
int root;//记录根的id
int minn_id;
int pnum;//人口总数
int suit;double avesuit;
int area;double avearea;
}b[N];
int tree[N];//建立一棵并查集,tree[i]=x,x表示i的父节点
int vis[N];//记录i是否记录进了人数
int getfa(int x){
if(x==tree[x])
return x;
return tree[x]=getfa(tree[x]);
}
void add(int x,int y){
int fa=getfa(x);
int fb=getfa(y);
if(fa!=fb){
tree[fa]=fb;
}
}
void init(family &x){
x.area=;x.suit=;
x.minn_id=;x.pnum=;
}
int fact1id(int i){
int num=i;
if(a[i].mo!=-)
num=min(a[i].mo,num);
if(a[i].fa!=-)
num=min(a[i].fa,num);
for(int j=;j<=a[i].k;j++){
num=min(a[i].kids[j],num);
}
return num;
}
int fact2(int i){
int num=;
if(vis[i]==){//别把自己也忘了!
num++;vis[i]=;
}
if(a[i].mo!=-&&vis[a[i].mo]==){
num++;vis[a[i].mo]=;
} if(a[i].fa!=-&&vis[a[i].fa]==){
num++;vis[a[i].fa]=;
}
for(int j=;j<=a[i].k;j++){
if(vis[a[i].kids[j] ]==)continue;
num++;
vis[a[i].kids[j] ]=;
}
return num;
}
bool cmp(family x,family y){
if(fabs(x.avearea-y.avearea)<1e-)
return x.minn_id<y.minn_id;
return x.avearea>y.avearea;
}
int main(){
int i,j,n;
scanf("%d",&n);
memset(vis,,sizeof(vis));
for(int i=;i<=;i++){
tree[i]=i;
a[i].area=-;
}
while(n--){
int id;
scanf("%d",&id);
scanf("%d%d",&a[id].fa,&a[id].mo);//确认并查集树上的父子关系
if(a[id].fa!=-){
add(id,a[id].fa);
}
if(a[id].mo!=-){
add(id,a[id].mo);
}
getfa(id); scanf("%d",&a[id].k);
for(int i=;i<=a[id].k;i++){//读入他的k个孩子的ID
scanf("%d",&a[id].kids[i]);
add(id,a[id].kids[i]);
}
scanf("%d%d",&a[id].suit,&a[id].area);
}
for(int i=;i<=;i++)//并查集重新调整一次!
getfa(i); int cnt=;//统计家庭数
set<int>s;//记录根节点
for(int i=;i<=;i++){
if(a[i].area==-){//不存在
continue;
}
int fa=tree[i];
int k;//表示开的family数组的序号
if(s.count(fa)>){
for(int j=;j<=cnt;j++){
if(b[j].root==fa){
k=j;break;
}
}
}else{
s.insert(fa);
++cnt;
k=cnt;
b[cnt].root=fa;//需要添加,别忘记了
init(b[k]);
}
//将a[i]数组的内容转移到b[k]中 b[k].area+=a[i].area;
b[k].minn_id=min(b[k].minn_id,fact1id(i) );
b[k].pnum+=fact2(i);
b[k].suit+=a[i].suit;
}
for(int i=;i<=cnt;i++){
b[i].avearea=b[i].area*1.0/(1.0*b[i].pnum);
b[i].avesuit=b[i].suit*1.0/(1.0*b[i].pnum);
}
sort(b+,b++cnt,cmp); printf("%d\n",cnt);
for(int i=;i<=cnt;i++){
printf("%04d %d %.3lf %.3lf\n",b[i].minn_id,b[i].pnum,b[i].avesuit,b[i].avearea);
} return ;
}

【PAT-并查集-水题】L2-007-家庭房产的更多相关文章

  1. Brain Network (easy)(并查集水题)

    G - Brain Network (easy) Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  2. poj2524(并查集水题)

    题目链接:http://poj.org/problem?id=2524 题目大意:学校共有n个同学,告诉你m对同学信仰同一宗教,问这个学校学生信仰宗教的数目最多为多少. 例: Sample Input ...

  3. POJ2524并查集水题

    Description There are so many different religions in the world today that it is difficult to keep tr ...

  4. HDU1863(Kruskal+并查集水题)

    https://cn.vjudge.net/problem/HDU-1863 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可). ...

  5. PAT题解-1118. Birds in Forest (25)-(并查集模板题)

    如题... #include <iostream> #include <cstdio> #include <algorithm> #include <stri ...

  6. PAT甲级 并查集 相关题_C++题解

    并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...

  7. 【HDU1231】How Many Tables(并查集基础题)

    什么也不用说,并查集裸题,直接盲敲即可. #include <iostream> #include <cstring> #include <cstdlib> #in ...

  8. poj1182 食物链(并查集 好题)

    https://vjudge.net/problem/POJ-1182 并查集经典题 对于每只动物创建3个元素,x, x+N, x+2*N(分别表示x属于A类,B类和C类). 把两个元素放在一个组代表 ...

  9. PAT甲题题解-1114. Family Property (25)-(并查集模板题)

    题意:给出每个人的家庭成员信息和自己的房产个数与房产总面积,让你统计出每个家庭的人口数.人均房产个数和人均房产面积.第一行输出家庭个数,随后每行输出家庭成员的最小编号.家庭人口数.人均房产个数.人均房 ...

随机推荐

  1. Consul 快速入门 - Kong最佳实践

    Consul是什么 Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用.限流.熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便.它提供了一个功 ...

  2. Office 2010 经验总结

    1. 如何设置蓝底白字? 答:点击菜单项上的"页面布局"→"页面颜色",就可以选择喜欢的页面颜色,字体颜色也会跟着发生改变. 补充:如果不喜欢相应的页面颜色中系 ...

  3. [转帖]04-创建kubeconfig认证文件

    04-创建kubeconfig认证文件 https://www.cnblogs.com/guigujun/p/8366530.html 学习一下 貌似挺有用的. 本文档记录自己的学习历程! 创建 ku ...

  4. ubuntu mysql5.7设置Open Files Limit

    目的:解决Too many open files异常 方式:设置Open Files Limit 环境:(MySQL)Server version: 5.7.27-0ubuntu0.16.04.1 ( ...

  5. SpringBoot中使用@Scheduled创建定时任务

    SpringBoot中使用@Scheduled创建定时任务 定时任务一般会在很多项目中都会用到,我们往往会间隔性的的去完成某些特定任务来减少服务器和数据库的压力.比较常见的就是金融服务系统推送回调,一 ...

  6. PHP中的PDO数据对象

    PDO: PHP Data Object:php的数据对象.pdo是数据库操作工具类!1,它能操作很多种数据库,比如mysql,oracle,sybase....2,它具有操作数据库的更多的功能,比如 ...

  7. csdn博客整理

    @TOC 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页.如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown ...

  8. python 之 前端开发( JavaScript变量、数据类型、内置对象、运算符、流程控制、函数)

    11.4 JavaScript 11.41 变量 1.声明变量的语法 // 1. 先声明后定义 var name; // 声明变量时无需指定类型,变量name可以接受任意类型 name= " ...

  9. 《Java Web开发实战》——Java工程师必备干货教材

    一年一度毕业季,又到了简历.offer漫天飞,失望与希望并存的时节.在IT行业,高校毕业生求职时,面临的第一道门槛就是技能与经验的考验,但学校往往更注重学生的理论知识,忽略了对学生实践能力的培养,因而 ...

  10. oracle笔记之计算年龄、工龄和TRUNC

    方法一:利用months_between 函数计算 SELECT TRUNC(months_between(sysdate, birthday)/12) AS agefrom dual; 方法二:日期 ...