L2-007. 家庭房产
时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。
输入格式:
输入第一行给出一个正整数N(<=1000),随后N行,每行按下列格式给出一个人的房产:
编号 父 母 k 孩子1 ... 孩子k 房产套数 总面积
其中 编号 是每个人独有的一个4位数的编号;父 和 母 分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0<=k<=5)是该人的子女的个数;孩子i是其子女的编号。
输出格式:
首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:
家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积
其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。
输入样例:10 6666 5551 5552 1 7777 1 100 1234 5678 9012 1 0002 2 300 8888 -1 -1 0 1 1000 2468 0001 0004 1 2222 1 500 7777 6666 -1 0 2 300 3721 -1 -1 1 2333 2 150 9012 -1 -1 3 1236 1235 1234 1 100 1235 5678 9012 0 1 50 2222 1236 2468 2 6661 6662 1 300 2333 -1 3721 3 6661 6662 6663 1 100输出样例:
3 8888 1 1.000 1000.000 0001 15 0.600 100.000 5551 4 0.750 100.000
思路:把出现的每个编号都标记下表示这个人是存在的,便于以后查找,然后没给出一条信息,里面包含它本身编号父母孩子编号,用并查集把他们联系在一起,并把最终父节点定位最小的,之后遍历所有点。通过查找父亲节点把房产数量房产面积和人数都加上即可并算平均值
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 11000;
int vis[maxn],m[maxn];//vis标记每个人,m标记最小的编号(父亲)
int p[maxn];
struct node{
double ans1,ans2;//ans1表示房子的数量,ans2表示面积
int id,num;//成员数量
};
bool cmp(node a,node b){
if(a.ans2 != b.ans2)
return a.ans2 > b.ans2;
return a.id < b.id;
}//按要求排序
void init(){
for(int i = 0; i < maxn; i++){
p[i] = i;
}
}
int Find(int x){
if(x == p[x])
return x;
else return p[x] = Find(p[x]);
}
void Union(int x,int y){
int fx = Find(x),fy = Find(y);
if(fx != fy){
if(fx > fy)
p[fx] = fy;
else
p[fy] = fx;
}
}
int main(){
int n;
node a[maxn],b[maxn],mul[maxn];
scanf("%d",&n);
init();
memset(vis,0,sizeof(vis));
memset(m,0,sizeof(m));
for(int i = 0; i < n; i++){
int p1,p2,d,k;
scanf("%d%d%d",&a[i].id,&p1,&p2);
vis[a[i].id] = 1;
if(p1 != -1){
Union(p1,a[i].id);
vis[p1] = 1;
}
if(p2 != -1){
Union(p2,a[i].id);
vis[p2] = 1;
}
scanf("%d",&k);
while(k--){
scanf("%d",&d);
if(d != -1){
Union(d,a[i].id);
vis[d] = 1;
}
}
scanf("%lf%lf",&a[i].ans1,&a[i].ans2);
}
//把同一家的房产数和面积加到最小编号上
for(int i = 0; i < n; i++){
int id = Find(a[i].id);
mul[id].id = id;
mul[id].ans1 += a[i].ans1;
mul[id].ans2 += a[i].ans2;
}
//把一家的总人数加到最小编号上
for(int i = 0; i < maxn; i++){
if(vis[i]){//如果这个人存在,找到父亲,人数加一
mul[Find(i)].num++;
}
}
int cnt = 0;
for(int i = 0; i < maxn; i++){
if(vis[i]){
int id = Find(i);
if(!m[id]){//储存答案
m[id] = 1;
double x = (double)mul[id].num;
b[cnt].ans1 = mul[id].ans1 * 1.0 / x;
b[cnt].ans2 = mul[id].ans2 * 1.0 / x;
b[cnt].id = id;
b[cnt++].num = (int)x;
}
}
}
printf("%d\n",cnt);
sort(b,b+cnt,cmp);
for(int i = 0; i < cnt; i++){
printf("%04d %d %.3f %.3f\n",b[i].id,b[i].num,b[i].ans1,b[i].ans2);
}
return 0;
}