1114 Family Property-PAT甲级

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 NNN (≤1000\le 1000≤1000). Then NNN lines follow, each gives the infomation of a person who owns estate in the format:

ID Father Mother kkk Child1⋯ChildkChild_1 \cdots Child_kChild​1​​⋯Child​k​​ MestateM_{estate}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); kkk (0≤k≤50\le k\le 50≤k≤5) is the number of children of this person; ChildiChild_iChild​i​​'s are the ID's of his/her children; MestateM_{estate}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 AVGsetsAVG_{sets}AVG​sets​​ AVGareaAVG_{area}AVG​area​​

where ID is the smallest ID in the family; M is the total number of family members; AVGsetsAVG_{sets}AVG​sets​​ is the average number of sets of their real estate; and AVGareaAVG_{area}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

解题方法:采用结构体来存储人的编号,家族人的数量,以及mestata和area;

在输入每一行时,父母与孩子的编号,如果没有访问过,则置一个结构体,否则,不进行更改,有可能他们已经作为第一个结点出现过,更改会影响mestata以及area的数值

同时,注意编号是4位的编号,应包括0在内,我一开始在最后找有几个家族遍历所有成员的时候是从1开始的,导致三个样例过不了,更改为0后通过全部样例,同时应该注意平时在写数组的时候注意不要越界,上越界以及下越界都会导致程序出错

满分代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=10005;
int vst[N];
set<int>st;
struct person{
	int id,sum=0;
	double mestate=0,area=0;
	person(){};
	person(int idd,int ssum,double mm,double aa){
		id=idd;
		sum=ssum;
		mestate=mm;
		area=aa;
	}
	bool operator < (const person &p)const{
		if(area!=p.area)
			return area>p.area;
		return id<p.id;
	}
}ps[N];
int n;
int fa[N];
//并查集
void init(){//初始化父节点 
	for(int i=1;i<=N;i++){
		fa[i]=i;
	}
} 
int get(int x){//寻找父节点 
	if(fa[x]==x)
		return x;
	return fa[x]=get(fa[x]);
}
void merge(int x,int y){
	//合并
	x=get(x);
	y=get(y);
	if(x!=y){
		fa[max(x,y)]=min(x,y);//父节点为较小的结点 
	} 
}
bool same(int x,int y){
	return get(x)==get(y);
}
int main(){
	init();
	cin>>n;
	fill(vst,vst+N,0);
	for(int i=1;i<=n;i++){
		int id,fid,mid,num,child[8];
		double mestate,area;
		cin>>id>>fid>>mid>>num;
		if(!vst[fid]&&fid!=-1){
			ps[fid]=person(fid,0,0,0);
			vst[fid]=1;
		}
		if(!vst[mid]&&mid!=-1){
			ps[mid]=person(mid,0,0,0);
			vst[mid]=1;
		}	
		vst[id]=1;
		if(fid!=-1&&!same(id,fid)){//合并一家人的结点 
			merge(id,fid);
		}
		if(mid!=-1&&!same(id,mid)){
			merge(id,mid);
		}
		for(int i=1;i<=num;i++){
			cin>>child[i];
			if(!vst[child[i]])
				ps[child[i]]=person(child[i],0,0,0);
			vst[child[i]]=1;
			if(!same(id,child[i])){
			merge(id,child[i]);
			}
			
		}
		cin>>mestate>>area;
		ps[id]=person(id,0,mestate,area);
	
	}
	for(int i=0;i<=N;i++){
		if(!vst[i]) continue;
		if(get(i)==i){
			ps[i].sum++;
			st.insert(i);
			continue;
		}else{
			int x=get(i);
			st.insert(x);
			ps[x].sum++;
			ps[x].mestate+=ps[i].mestate;		
			ps[x].area+=ps[i].area;
		}
	}
	cout<<st.size()<<endl;
	person pe[st.size()+3];
	int jj=0;
    for(auto i=st.begin();i!=st.end();i++){
    	pe[jj]=ps[*i];
    	pe[jj].area=pe[jj].area/pe[jj].sum;
    	jj++;
	}
		
	sort(pe,pe+st.size());
	for(int i=0;i<st.size();i++){
		printf("%04d %d %.3f %.3f\n",pe[i].id,pe[i].sum,pe[i].mestate/pe[i].sum,pe[i].area);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值