写在前面
- 思路分析
- 给定每个人的家庭成员和其⼰己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。
- 首先在第1行输出家庭个数(所有有亲属关系的人都属于同1个家庭)
- 随后按下列格式输出每个家庭的信息:
- 家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积。其中人均值保留小数点后3位。
- 家庭信息按人均面积降序输出,若有并列,则按成员编号的升序输出
- 分析实现:并查集
- 2类结构体数组,1个data用来接收数据,接收时顺便实现并查集操作union,另1个数组ans输出最后答案
- 要计算家庭人数,所以用visit标记所有出现过结点,对于每个结点的父结点, people++统计人数
- 标记flag == true,计算true的个数cnt就可以知道1共有多少个家庭
- 排序后输出前cnt个就是所求答案
- 并查集,核心知识点
- 学习ing,锻炼短时间设计并实现工程方案的能力
- 第1遍
测试用例
-
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 output: 3 8888 1 1.000 1000.000 0001 15 0.600 100.000 5551 4 0.750 100.000
ac代码
-
#include <cstdio> #include <algorithm> using namespace std; struct DATA { int id, fid, mid, num, area; int cid[10]; } data[1005]; struct node { int id, people; double num, area; bool flag = false; } ans[10000]; int father[10000]; bool visit[10000]; int findFather(int x) { int a = x; while(x != father[x]) x = father[x]; while(a!=father[a]) { int z = a; a = father[a]; father[z] = x; } return x; } void Union(int a, int b) { int faA = findFather(a); int faB = findFather(b); if(faA > faB) father[faA] = faB; else if(faA < faB) father[faB] = faA; } int cmp1(node a, node b) { if(a.area != b.area) return a.area > b.area; else return a.id < b.id; } int main() { int n, k, cnt = 0; scanf("%d", &n); for(int i = 0; i < 10000; i++) father[i] = i; for(int i = 0; i < n; i++) { scanf("%d %d %d %d", &data[i].id, &data[i].fid, &data[i].mid, &k); visit[data[i].id] = true; // 并查集合并 if(data[i].fid != -1) { visit[data[i].fid] = true; Union(data[i].fid, data[i].id); } if(data[i].mid != -1) { visit[data[i].mid] = true; Union(data[i].mid, data[i].id); } // 读取并并查孩子结点 for(int j = 0; j < k; j++) { scanf("%d", &data[i].cid[j]); visit[data[i].cid[j]] = true; Union(data[i].cid[j], data[i].id); } scanf("%d %d", &data[i].num, &data[i].area); } // 递归遍历求和、财产数、房屋总面积 for(int i = 0; i < n; i++) { int id = findFather(data[i].id); ans[id].id = id; ans[id].num += data[i].num; ans[id].area += data[i].area; ans[id].flag = true; } for(int i = 0; i < 10000; i++) { // 以根节点建立数组并记录人数 if(visit[i]) ans[findFather(i)].people++; // 记录家族个数 if(ans[i].flag) cnt++; } for(int i = 0; i < 10000; i++) { if(ans[i].flag) { ans[i].num = (double)(ans[i].num * 1.0 / ans[i].people); ans[i].area = (double)(ans[i].area * 1.0 / ans[i].people); } } sort(ans, ans + 10000, cmp1); printf("%d\n", cnt); for(int i = 0; i < cnt; i++) printf("%04d %d %.3f %.3f\n", ans[i].id, ans[i].people, ans[i].num, ans[i].area); return 0; }