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;
}