PAT (Advanced Level) Practice 1114 Family Property (25 分)
1114 Family Property (25 分)
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
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
題目大意:輸入N個家族的成員、房產數量和麵積,輸出每個大家族中編號最小的人,家族成員數量,家族房產平均數量。
題解1:
思路:並查集。
對每個家族,輸入的時候選擇編號最小的人作為父親,進行合併。
每個家族的第一個人,把房產數量和麵積記到他的名下。
所有的家族輸入後,更新所有人的父親(保證每個人都找到了真正的父節點)。
遍歷,找到每個家族的最小編號,把所有房產改到他的名下,並記錄總家族數。
排序,輸出。
注意事項:
1.比較的時候,由於每個人所記的家族成員數量、房產資訊不一樣(非父節點不記錄家族成員數量),如果初始化成員數量,房產數量和麵積都為0,會導致比較出錯。修改:初始化成員數量為1(即他自己)(後面統計成員數量的時候注意不要重複加上父節點自己),初始化房產數量和麵積都為0,用乘法代替除法進行房產面積平均值比較。
2.每個人的編號是一個4位數字,包括0000。
3.初始化book=-1,用來區分該編號的成員是否存在。
4.使用vector記錄成員資訊應該可以減少很多記憶體,不過這裡用陣列通過了,就暫時沒有嘗試vector。
原始碼1:
#include<iostream>
#include<algorithm>
#include<map>
#include<stdlib.h>
#include<vector>
using namespace std;
struct node
{
int id=10000, book = -1, cnt = 1, num = 0, area = 0;
};
bool cmp(node a, node b)
{
if (a.area * b.cnt != b.area * a.cnt)return a.area * b.cnt > b.area * a.cnt;
else return a.id < b.id;
}
node person[10001];
int getfather(int x)
{
if (x == person[x].book)return x;
else return person[x].book = getfather(person[x].book);
}
void merge(int x, int y)
{
int fx, fy;
fx = getfather(x);
fy = getfather(y);
if(fx<fy)person[fy].book = fx;
else person[fx].book = fy;
return;
}
int main()
{
int n, k, htemp, ftemp, i, j,mmax=0;
map<int, int>mmap;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
int self, others;
scanf("%d", &self);
if(person[self].book ==-1)person[self].book=person[self].id= self;
for (j = 0; j < 2; j++)
{
scanf("%d", &others);
if (others != -1)
{
if (person[others].book == -1)person[others].book = person[others].id = others;
merge(self, others);
}
}
scanf("%d", &k);
for (j = 0; j < k; j++)
{
scanf("%d", &others);
if (person[others].book == -1)person[others].book = person[others].id = others;
merge(self,others);
}
scanf("%d %d", &person[self].num, &person[self].area);
}
for (i = 0; i <= 10000; i++)
if(person[i].book!=-1)getfather(i);
mmax = 0;
for (i = 0; i < 10001; i++)
{
if (person[i].book != -1)
{
if (person[i].book == i)mmax++;
else
{
person[person[i].book].num += person[i].num;
person[i].num = 0;
person[person[i].book].area += person[i].area;
person[i].area = 0;
person[person[i].book].cnt++;
}
}
}
sort(person, person+10001, cmp);
printf("%d\n", mmax);
for (i = 0; i < mmax; i++)
printf("%04d %d %.3lf %.3lf\n", person[i].id, person[i].cnt, 1.0*person[i].num/person[i].cnt, 1.0*person[i].area/person[i].cnt);
system("pause");
return 0;
}