题目详情 - 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 }