PAT 1114 Family Property

原题链接:1114 Family Property (25分)
关键词:并查集

这次,需要你帮我们整理关于家庭财产方面的数据。

给定每个人的家庭成员以及他/她自己名字下的不动产(地产)信息,我们需要知道每个家庭的成员数,以及人均不动产面积和人均房产套数。

输入格式

第一行包含整数 N。

接下来 N 行,每行包含一个拥有房产的人员的信息,格式如下:

ID Father Mother k Child_1 ... child_k M_estate Area
其中 ID 是每个人的独一无二的 4 位数标识号,FatherMother 是这个人的父母的 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值