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⋯Childk Mestate 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; Childi's are the ID
's of his/her children; Mestate 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 AVGarea
where ID
is the smallest ID in the family; M
is the total number of family members; AVGsets is the average number of sets of their real estate; and AVGarea 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
题目大意:给定每个人的家庭成员和其自己名下的房产,请统计出每个家庭的人口数、人均房产面积及房产套数。首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积。其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。
分析:并查集。这里用哈希表模拟了。将同一个家庭的成员用flag标记成同一个数字,统计有多少不同的flag,相同flag的情况下,有多少人,最小编号,房产总数,房产面积总数并存储,最后输出。
注意0000也是有效的成员编号。
#include<algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <map>
#include <set>
#define INF 0xffffffff
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<endl
#define db5(x,y,z,r,w) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<", "<<#w<<"="<<(w)<<endl
using namespace std;
typedef struct node//家庭成员结构
{
int id,flag;//自己的编号,以及对应家庭的编号
int fat,mon;//父母的编号
int m,area;//自己有多少房产和房产面积
}node;
typedef struct family//因为是哈希表存储的成员,最后需要把所有成员拿出来排序
{
int id,sum;//该成员的编号,家庭人数总和
double sets,area;//这一家庭的平均套数和平均面积
}family;
bool cmpnode(node a,node b)//快排比较函数
{
return a.flag<b.flag;
}
bool cmpans(family a,family b)//快排比较函数
{
if(a.area!=b.area)return a.area>b.area;
return a.id<b.id;
}
int main(void)
{
#ifdef test
freopen("in.txt","r",stdin);
//freopen("in.txt","w",stdout);
clock_t start=clock();
#endif //test
int n,cnt=1;scanf("%d",&n);
node num[10010];//初始化哈希表
for(int i=0;i<10000;++i)
num[i].id=i,num[i].flag=num[i].fat=num[i].mon=-1,num[i].area=num[i].m=0;
for(int i=0;i<n;++i)
{
int a,index=cnt;scanf("%d",&a);
scanf("%d%d",&num[a].fat,&num[a].mon);
if(num[a].flag!=-1)//如果当前成员已经是某个家庭的成员
{//如果父亲或者母亲是某个家庭的成员,需要合并集合,所有被标记的全部改为当前节点标记
index=num[a].flag;
if(num[a].fat!=-1&&num[a].mon!=-1)//如果父母都在
{
int temp1=num[num[a].fat].flag,temp2=num[num[a].mon].flag;
for(int i=1;i<10000;++i)
if((temp1!=-1&&num[i].flag==temp1)||(temp2!=-1&&num[i].flag==temp2))
num[i].flag=index;
num[num[a].fat].flag=num[num[a].mon].flag=index;
}
else if(num[a].fat!=-1)//父亲在,母亲不在
{
int temp1=num[num[a].fat].flag;
for(int i=1;i<10000;++i)
if(temp1!=-1&&num[i].flag==temp1)
num[i].flag=index;
}
else if(num[a].mon!=-1)//母亲在,父亲不在
{
int temp2=num[num[a].mon].flag;
for(int i=1;i<10000;++i)
if(temp2!=-1&&num[i].flag==temp2)
num[i].flag=index;
}
}
else if(num[a].fat!=-1&&num[num[a].fat].flag!=-1)
{//父亲被标记过,同步成父亲的标记
index=num[num[a].fat].flag;
num[a].flag=index;
if(num[a].mon!=-1)
{
int temp2=num[num[a].mon].flag;
for(int i=0;i<10000;++i)
if(temp2!=-1&&num[i].flag==temp2)
num[i].flag=index;
num[num[a].mon].flag=index;
}
}
else if(num[a].mon!=-1&&num[num[a].mon].flag!=-1)
{//母亲被标记过,同步成母亲的标记
index=num[num[a].mon].flag;
num[a].flag=index;
if(num[a].fat!=-1)
{
int temp1=num[num[a].fat].flag;
for(int i=0;i<10000;++i)
if(temp1!=-1&&num[i].flag==temp1)
num[i].flag=index;
num[num[a].fat].flag=index;
}
}
else//都没被标记,全部标记成新的标记
{
index=cnt;num[a].flag=num[num[a].fat].flag=num[num[a].mon].flag=index;cnt++;
}
int k;scanf("%d",&k);
while(k--)//孩子部分同样考虑是否被标记
{
int aa;scanf("%d",&aa);
if(num[aa].flag!=-1)
{
int temp=num[a].flag;index=num[aa].flag;
for(int i=0;i<10000;++i)
if(num[i].flag==temp)num[i].flag=index;
}
else num[aa].flag=index;
}
scanf("%d%d",&num[a].m,&num[a].area);
}
int total_num=0;
node val[10005];
for(int i=0;i<10000;++i)
{
if(num[i].flag!=-1)val[total_num++]=num[i];
}
sort(val,val+total_num,cmpnode);
// for(int i=0;i<total_num;++i)
// db4(val[i].id,val[i].flag,val[i].m,val[i].area);
family ans[total_num+5];
int tempflag=val[0].flag,ans_num=0,miniid=val[0].id,cntnum=1,setnum=val[0].m,areanum=val[0].area;
for(int i=1;i<total_num;++i)
{
if(val[i].flag==tempflag)
{
miniid=min(val[i].id,miniid);cntnum++;setnum+=val[i].m,areanum+=val[i].area;
}
else
{
ans[ans_num].id=miniid;
ans[ans_num].sum=cntnum;
ans[ans_num].sets=1.0*setnum/cntnum;
ans[ans_num].area=1.0*areanum/cntnum;
ans_num++;
tempflag=val[i].flag,miniid=val[i].id,cntnum=1,setnum=val[i].m,areanum=val[i].area;
}
}
ans[ans_num].id=miniid;
ans[ans_num].sum=cntnum;
ans[ans_num].sets=1.0*setnum/cntnum;
ans[ans_num].area=1.0*areanum/cntnum;
ans_num++;
printf("%d\n",ans_num);
sort(ans,ans+ans_num,cmpans);
for(int i=0;i<ans_num;++i)
{
printf("%04d %d %.3f %.3f\n",ans[i].id,ans[i].sum,ans[i].sets,ans[i].area);
}
#ifdef test
clockid_t end=clock();
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
printf("\n\n\n\n\n");
cout<<"Total time:"<<endtime<<"s"<<endl; //s为单位
cout<<"Total time:"<<endtime*1000<<"ms"<<endl; //ms为单位
#endif //test
return 0;
}