PAT 甲级 1114 Family Property

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a845717607/article/details/87894725

1114 Family Property (25 point(s))

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 Child​1​​⋯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 AVG​sets​​ 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

经验总结:

这一题.....还是稍微有点复杂的,不过并查集的题目都不是很难,注意这么几点:
并查集的合并必须在所有数据输入完成后再进行,因为合并时需要进行资产以及房屋面积的合并,而合并中的成员的数据可能还未读到,所以,必须把父母以及孩子的id存储,在输入完成后再进行合并。
合并的时候,让id小的一方当父结点,更新父结点的资产,人数,以及房屋面积。
查找时,由于初始化所有的结点的父结点都是自己,这里要使用一个flag数组记录那些在题目里出现过的结点id,从这些id里面寻找父结点为自己的结点,这个结点就是这一个家族里id最小的结点,然后再进行排序输出,就可以啦~

AC代码

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=10010;
int n,father[maxn];
bool flag[maxn]={false};
struct node
{
	int area,setnum,num,ba,ma;
	vector<int> child;
	double avearea;
	node():num(1),area(0),setnum(0){}
}Node[maxn];
bool cmp(int a,int b)
{
	if(Node[a].avearea!=Node[b].avearea)
		return Node[a].avearea>Node[b].avearea;
	return a<b;
}
int findFather(int x)
{
	int a=x;
	while(x!=father[x])
		x=father[x];
	while(a!=father[a])
	{
		int z=father[a];
		father[a]=x;
		a=z;
	}
	return x;
}
void Union(int a,int b)
{
	int a1=findFather(a);
	int b1=findFather(b);
	if(a1!=b1)
	{
		if(a1>b1)
			swap(a1,b1);
		father[b1]=a1;
		Node[a1].num+=Node[b1].num;
		Node[a1].area+=Node[b1].area;
		Node[a1].setnum+=Node[b1].setnum;
	}
}
int main()
{
	scanf("%d",&n);
	int id,ba,ma,k;
	vector<int> child,save;
	for(int i=0;i<maxn;++i)
		father[i]=i;
	for(int i=0;i<n;++i)
	{
		scanf("%d",&id);
		scanf("%d%d%d",&Node[id].ba,&Node[id].ma,&k);
		save.push_back(id);
		Node[id].child.resize(k);
		for(int j=0;j<k;++j)
			scanf("%d",&Node[id].child[j]);
		scanf("%d%d",&Node[id].setnum,&Node[id].area);
	}
	for(int i=0;i<save.size();++i)
	{
		int id=save[i];
		flag[id]=true;
		if(Node[id].ba!=-1)
		{
			flag[Node[id].ba]=true;
			Union(id,Node[id].ba);
		}
		if(Node[id].ma!=-1)
		{
			flag[Node[id].ma]=true;
			Union(id,Node[id].ma);
		}
		for(int j=0;j<Node[id].child.size();++j)
		{
			flag[Node[id].child[j]]=true;
			Union(id,Node[id].child[j]);
		}
	}
	vector<int> temp;
	for(int i=0;i<maxn;++i)
	{
		int fid=findFather(i);
		if(fid==i&&flag[fid]==true)
		{
			Node[fid].avearea=Node[fid].area*1.0/Node[fid].num;
			temp.push_back(fid);
		}
	}
	sort(temp.begin(),temp.end(),cmp);
	printf("%d\n",temp.size());
	for(int i=0;i<temp.size();++i)
	{
		int x=temp[i];
		printf("%04d %d %.3f %.3f\n",x,Node[x].num,Node[x].setnum*1.0/Node[x].num,Node[x].avearea);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a845717607/article/details/87894725