PAT甲级-1114-Family Property(并查集)

This time, you are supposed to help us collect the data for family-owned property. Given each person’s family members, and the estate(房产)info under his/her own name, we need to know the size of each family, and the average area and number of sets of their real estate.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤1000). Then N lines follow, each gives the infomation of a person who owns estate in the format:

ID Father Mother k Child1⋯Child​k M​estate Area

where ID is a unique 4-digit identification number for each person; Father and Mother are the ID’s of this person’s parents (if a parent has passed away, -1 will be given instead); k (0≤k≤5) is the number of children of this person; Child ​i’s are the ID’s of his/her children; M estate is the total number of sets of the real estate under his/her name; and Area is the total area of his/her estate.

Output Specification:

For each case, first print in a line the number of families (all the people that are related directly or indirectly are considered in the same family). Then output the family info in the format:

ID M AVGsets AVG​area

where ID is the smallest ID in the family; M is the total number of family members; AVG​sets is the average number of sets of their real estate; and AVG​area is the average area. The average numbers must be accurate up to 3 decimal places. The families must be given in descending order of their average areas, and in ascending order of the ID’s if there is a tie.

Sample Input:

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

Sample Output:

3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000

1、数据结构选择:

选择结构体数组data【1005】暂存输入的数据,结构体数组ans【10000】存放结果
(其中ans的下标和四位数的id是一一对应的)(sort以后下标便可从0开始了)

2、算法流程:

①统计家族财产(家族中所有成员把财产拿出来),存入ans【10000】中
②统计家族数以及各家族人数:
用flag标记是否为该家族老大(root),由于一个家族老大(root)代表一个家族,因此家族老大(root)数即家族数;用一维数组visit【10000】标记所有人员的访问情况,记录每一家族中的家族人数。(由于家族中的小孩一辈分可能是没有财产收入的,因此它的信息可能不在node[i].id中,所以输入的每一行中father,mother,child[j]都要用visit标识)

③精细加工, 家族财产/家族人数

代码如下

#include<iostream>
#include<algorithm>
using namespace std;
int Arry[10000];bool visit[10000];
struct dataInfo{
	int id,father,mother,sets,area;
	int child[10];
}data[1005];
struct node{
	int id,num;
	double sets,area;
	bool flag = false;
}ans[10000];//结构体数组下标正代表了它的编号id! 
int cmp(node a,node b){
	if(a.area != b.area) return a.area>b.area;
	return a.id<b.id;
}
int Find(int num)
{
	int root = num;
	while(Arry[root] != root){
		root = Arry[root]; 
	} 
	while(num != root){
		int tmp = Arry[num];
		Arry[num] = root;//Arry[num]之所以要暂存,就是因为它要被篡改! 
		num = tmp;
	}
	return num;
}
int Union(int a,int b)
{
	int aRoot = Find(a);
	int bRoot = Find(b);
	if(aRoot > bRoot) Arry[aRoot] = bRoot;
	else if(aRoot < bRoot) Arry[bRoot] = aRoot;
}
int main()
{
	int n,k,cnt=0;
	scanf("%d", &n);
	for(int i = 0; i < 10000; i++){
		Arry[i] = i;
	}
	for(int i = 0; i < n; i++){
		scanf("%d %d %d %d", &data[i].id,&data[i].father,&data[i].mother,&k);
		visit[data[i].id] = true;
		if(data[i].father != -1){
			visit[data[i].father] = true;
			Union(data[i].father,data[i].id);
		}
		if(data[i].mother != -1){
			visit[data[i].mother] = true;
			Union(data[i].mother,data[i].id);
		}
		for(int j = 0; j < k; j++) {
			scanf("%d", &data[i].child[j]);
			visit[data[i].child[j]] = true;
			Union(data[i].child[j],data[i].id);
		}
		scanf("%d %d", &data[i].sets, &data[i].area);
	}
	//统计家族财产(家族中所有成员把财产拿出来) 
	for(int i = 0; i < n; i++){
		int id = Find(data[i].id);
		ans[id].id = id;
		ans[id].sets += data[i].sets;
		ans[id].area += data[i].area;
		ans[id].flag = true;//表明该结点是父结点 
	}
	//统计家族人数 
	for(int i = 0; i < 10000; i++){
		if(visit[i]) ans[Find(i)].num++;
		if(ans[i].flag) cnt++;
	}
	//精细加工, 家族财产/家族人数  
	for(int i = 0; i < 10000; i++){
		if(ans[i].flag){
			ans[i].sets = ans[i].sets*1.0/ans[i].num;
			ans[i].area = ans[i].area*1.0/ans[i].num;
		}
	}
	sort(ans, ans+10000, cmp);
	cout<<cnt<<endl;
	for(int i = 0; i < cnt; i++){
		printf("%04d %d %.3f %.3f\n", ans[i].id,ans[i].num,ans[i].sets,ans[i].area);
	}
	return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值