A1114. Family Property

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 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; Childi'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

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string>
 5 #include<vector>
 6 using namespace std;
 7 double estate[10000], area[10000];
 8 int father[10000], familyNum[10000], tb[10000];
 9 bool cmp(int a, int b){
10     if(area[a] != area[b])
11         return area[a] > area[b];
12     else return a < b;
13 }
14 int findFather(int x){
15     int temp = x;
16     while(x != father[x]){
17         x = father[x];
18     }
19     int temp2;
20     while(temp != x){
21         temp2 = father[temp];
22         father[temp] = x;
23         temp = temp2;
24     }
25     return x;
26 }
27 void merge(int a, int b){
28     if(a == -1 || b == -1)
29         return;
30     int af = findFather(a);
31     int bf = findFather(b);
32     if(af == bf)
33         return;
34     if(af > bf)
35         swap(af, bf);
36     father[bf] = af;
37 }
38 int main(){
39     int N;
40     scanf("%d", &N);
41     int id, idf, idm, child;
42     int chiN;
43     for(int i = 0; i < 10000; i++){
44         estate[i] = 0;
45         area[i] = 0;
46         father[i] = i;
47         familyNum[i] = 0;
48         tb[i] = 0;
49     }
50     for(int i = 0; i < N; i++){
51         cin >> id >> idf >> idm >> chiN;
52         tb[id] = tb[idf] = tb[idm] = 1;
53         merge(id, idf);
54         merge(id, idm);
55         int son;
56         for(int j = 0; j < chiN; j++){
57             cin >> son;
58             tb[son] = 1;
59             merge(id, son);
60         }
61         cin >> estate[id] >> area[id];
62     }
63     int cnt = 0;
64     vector<int> ans;
65     for(int i = 0; i < 10000; i++){
66         if(tb[i] == 1){
67             int ff = findFather(i);
68             if(ff != i){
69                 estate[ff] += estate[i];
70                 area[ff] += area[i];
71             }
72             familyNum[ff]++;
73             if(i == ff){
74                 cnt++;
75                 ans.push_back(i);
76             }
77             
78         }
79     }
80     for(int i = 0; i < 10000; i++){
81         if(tb[i] == 1 && father[i] == i){
82             int Num = familyNum[i];
83             area[i] = area[i] / (double)Num;
84             estate[i] = estate[i] / (double)Num;
85         }
86     }
87     sort(ans.begin(), ans.end(), cmp);
88     printf("%d
", cnt);
89     for(int i = 0; i < ans.size(); i++){
90         printf("%04d %d %.3f %.3f
", ans[i], familyNum[ans[i]], estate[ans[i]], area[ans[i]]);
91     }
92     cin >> N;
93     return 0;
94 }
View Code

总结:

1、由于一个人既有双亲又有N多个孩子,所以用树形结构肯定不行。只能用并查集或者图搜索。

2、并查集:并查集仅仅对父母、子女的关系进行合并处理。房子数、面技数、家庭人口等先不计算,仅仅存在每个人各自的对应数组中。由于序号不是连续的1到N,因此father数组中会有很多无效节点,需要一个tb数组在输入的时候就记录哪些是有效的节点。 在并查集处理完家庭关系之后,对father数组再次遍历,当遇到非根节点时,查找到他对应的根节点,并把房子、面积、等累加至根节点对应的数组中。  

3、由于要求输出的id为家族中最小id,所以在两个root合并时,要将更小的root作为新的root。

原文地址:https://www.cnblogs.com/zhuqiwei-blog/p/8576568.html