原题链接:1114 Family Property (25分)
关键词:并查集
这次,需要你帮我们整理关于家庭财产方面的数据。
给定每个人的家庭成员以及他/她自己名字下的不动产(地产)信息,我们需要知道每个家庭的成员数,以及人均不动产面积和人均房产套数。
输入格式
第一行包含整数 N。
接下来 N 行,每行包含一个拥有房产的人员的信息,格式如下:
ID Father Mother k Child_1 ... child_k M_estate Area
其中 ID 是每个人的独一无二的 4 位数标识号,Father
和 Mother
是这个人的父母的 ID 号(父母去世则用 -1
代替),k
是孩子数量,Child_i
是孩子的 ID,M_estate
是其名下房产数量,Area
是其名下房产的总面积。
输出格式
每行输出一个家庭的相关房产信息,格式如下:
ID M AVG_sets AVG_area
其中 ID 是家庭成员中编号最小的成员编号,M
是家庭成员数,AVG_sets
是人均房产套数,AVG_area
是人均房产面积。
两个平均数都要保留三位小数。
按人均房产面积降序顺序输出所有家庭信息。
当存在人均房产面积相同的情况时,按 ID 升序顺序排序。
数据范围:
1≤N≤1000,
0≤k≤5
每个人名下房产不超过 100 套,
每个人名下房产总面积不超过 50000。
输入样例1:
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
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
int n,k;
struct Data{ //处理输入数据
int id,fid,mid;
int c[6];
int num,area;
};
struct Ans{ //答案的元素
int id,people;
double num,area;
bool flag;//flag是最终的父亲节点为true,多少个true,多少个家庭
};
Ans ans[maxn];
Data data1[maxn];
bool cmp(Ans a,Ans b)//答案输出的顺序
{
if(a.area != b.area) return a.area > b.area;
else return a.id < b.id;
}
int father[maxn];
bool alive[maxn];//判断是不是活着的
//并查集
int find(int x) {
return father[x] == x ? x : father[x] = find(father[x]);
}
void union1(int a, int b){ //合并到编号小的
int faA = find(a);
int faB = find(b);
if(faA > faB) father[faA] = faB;
else if(faA < faB) father[faB] = faA;
}
int main(){
scanf("%d",&n);
for(int i = 0; i < maxn; i++) father[i] = i; //并查集初始化
for(int i = 0; i < n; i++)
{
scanf("%d %d %d %d",&data1[i].id, &data1[i].fid, &data1[i].mid, &k);
alive[data1[i].id] = true;
if(data1[i].fid != -1){ //只处理还在的人
alive[data1[i].fid] = true;
union1(data1[i].fid, data1[i].id);
}
if(data1[i].mid != -1){ //只处理在的人
alive[data1[i].mid] = true;
union1(data1[i].mid, data1[i].id);
}
for(int j = 0; j<k; j++) //输入孩子
{
scanf("%d",&data1[i].c[j]);
alive[data1[i].c[j]] = true;
union1(data1[i].c[j], data1[i].id);
}
scanf("%d %d", &data1[i].num, &data1[i].area);
}
for(int i = 0; i < n; i++) {
int id = find(data1[i].id);//找出最父亲的节点,把data[i]的所有东西都加到这个节点
ans[id].id = id;
ans[id].num += data1[i].num;
ans[id].area += data1[i].area;
ans[id].flag = true;
}
int cnt = 0; //家族的数目
for(int i = 0; i < maxn; i++)
{
if(alive[i]) //还活着的人
{
ans[find(i)].people++; //家族人数加1
}
if(ans[i].flag==true) cnt++;
}
for(int i = 0; i < maxn; i++)
{
if(ans[i].flag)
{
ans[i].num=(double)(ans[i].num*1.0/ans[i].people);
ans[i].area=(double)(ans[i].area*1.0/ans[i].people);
}
}
sort(ans, ans + maxn, cmp);
printf("%d\n", cnt);
for(int i = 0; i < cnt; i++)
printf("%04d %d %.3f %.3f\n", ans[i].id, ans[i].people, ans[i].num, ans[i].area);
return 0;
}