博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

题目详情 - 1114 Family Property (pintia.cn)

需求解的量 :

不同家族的个数,代表各家族的最小id号,各家族的人数,各家族的平均房产数,各家族的平均住房面积

具体解法:

使用并查集disjoint-set维护一个数组fa,使fa[x]保存元素x的父节点,对于树根xr有fa[xr] == xr .  使用get(int x)函数获取元素x的根节点,使用merge(int x, int y)函数把x及其路径上的节点挂到y的根上。ps.这里用了《算法竞赛进阶指南》中的模板

数据的输入阶段:

在allID数组中,用出现过的所有id(包括自己,双亲,子女的id)作为key/下标,将此内存单元置1 。

每一行输入的id使用merge函数合并,表示同一个家族,且需要让代表元素即根节点始终保持最小,那么在进行合并时先比较两个元素根节点的大小,确保让大根挂在小根上。

数据处理阶段:

遍历allID数组,非0单元的下标即为存在的id,对此下标使用get函数得到根节点,再以根节点作为key,在family数组中加1,最后此数组“非零单元的数值”是以“该单元下标为id的家族”的“人数”。

estate与area数组的处理思路相近,最后将各个值的答案用一个结构体保存,按题目要求排好序再输出。

 

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 int fa[10000], family[10000]; 
 6 int allID[10000], estate[10000], area[10000];
 7 struct ans{
 8     int id, num_memb; double avg_estate, avg_area;
 9     ans(int a=0, int b=0, double c=0, double d=0):id(a),num_memb(b),avg_estate(c),avg_area(d){}
10 };
11 int get(int x){
12     if (x == fa[x])  return x;
13     return  fa[x] = get(fa[x]);
14 }
15 void merge(int x, int y){ //把x及其路径上的节点挂到y的根上
16     fa[get(x)] = get(y);
17 }
18 bool cmp(ans x, ans y){
19     if (x.avg_area != y.avg_area) return x.avg_area > y.avg_area;
20     else return x.id < y.id;
21 }
22 int main()
23 {
24     
25     int n;  cin >> n;
26     for (int i=0; i<=9999; ++i) {fa[i] = i;}
27     for (int i=0; i<n; ++i){
28         int a, b, c, d;
29         cin >> a >> b >> c >> d;
30         allID[a]=1;    
31         if (b != -1){
32              allID[b]=1;
33              if (get(a)>get(b)) merge(a,b);  else  merge(b,a);
34         }
35         if (c != -1) {
36             allID[c]=1;
37              if (get(a)>get(c)) merge(a,c);  else  merge(c,a);
38         }
39         while (d--){
40             int child;  cin >> child;
41             if (get(a)>get(child)) merge(a,child);  else  merge(child,a);
42             allID[child]=1;
43         }
44         int e, f;  cin >> e >> f;
45         estate[a] = e;  area[a]=f;
46     }
47     for (int i=0; i<10000; ++i){
48         if (allID[i]){ 
49             int root = get(i);
50             family[root]++; // root作下标的家族的人数
51             if (i != root) estate[root] += estate[i];
52             if (i != root) area[root] += area[i];
53         }
54     }
55     vector<ans>  Ans; int total_fam=0;
56     for (int i=0; i<10000; ++i){
57         int a, b; double c, d;
58         if (family[i]){
59             a = i;    b = family[i];
60             c = (double)estate[i]/b; 
61             d = (double)area[i]/b;
62             Ans.push_back(ans(a,b,c,d));  total_fam++;
63         }
64     }  cout << total_fam << "\n";
65     sort(Ans.begin(), Ans.end(), cmp);
66     for (int i=0; i<Ans.size(); ++i){
67         printf("%04d %d %.3f %.3f\n",Ans[i].id, Ans[i].num_memb, Ans[i].avg_estate, Ans[i].avg_area);
68     }
69     return 0;
70 }

 

posted on 2023-05-12 10:54  voyaging  阅读(8)  评论(0编辑  收藏  举报