题目地址:
https://www.acwing.com/problem/content/description/1606/
这次,需要你帮我们整理关于家庭财产方面的数据。给定每个人的家庭成员以及他/她自己名字下的不动产(地产)信息,我们需要知道每个家庭的成员数,以及人均不动产面积和人均房产套数。
输入格式:
第一行包含整数
N
N
N。
接下来
N
N
N行,每行包含一个拥有房产的人员的信息,格式如下:
ID Father Mother k Child_1 ... child_k M_estate Area
其中ID是每个人的独一无二的
4
4
4位数标识号,Father和Mother是这个人的父母的 ID 号(父母去世则用
−
1
-1
−1代替),
k
k
k是孩子数量,Child_i是孩子的ID,M_estate是其名下房产数量,Area是其名下房产的总面积。
输出格式:
每行输出一个家庭的相关房产信息,格式如下:
ID M AVG_sets AVG_area
其中ID是家庭成员中编号最小的成员编号,M是家庭成员数,AVG_sets是人均房产套数,AVG_area是人均房产面积。
两个平均数都要保留三位小数。
按人均房产面积降序顺序输出所有家庭信息。
当存在人均房产面积相同的情况时,按ID升序顺序排序。
数据范围:
1
≤
N
≤
1000
1≤N≤1000
1≤N≤1000,
0
≤
k
≤
5
0≤k≤5
0≤k≤5,
每个人名下房产不超过
100
100
100套,
每个人名下房产总面积不超过
50000
50000
50000。
思路是并查集。将家庭关系用并查集维护,并且开若干个数组,记录每个家庭的人数、最小ID、房产总套数和房产总面积。最后做一个归总。注意比较人均面积的时候,可以用整数乘法来做,而不是除法,因为比较double是不精确的。代码如下:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int N = 10010;
int n;
int p[N], cnt[N], cnt_house[N], area[N], min_id[N];
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
void init(int x) {
if (!~p[x]) p[x] = x;
}
void merge(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return;
p[px] = py;
cnt[py] += cnt[px];
cnt_house[py] += cnt_house[px];
area[py] += area[px];
min_id[py] = min(min_id[px], min_id[py]);
}
struct Info {
int ID;
int M;
int TOT_CNT;
int TOT_AREA;
};
int main() {
for (int i = 0; i < N; i++) {
p[i] = -1;
cnt[i] = 1;
min_id[i] = i;
}
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int id, fa, mo, k;
scanf("%d%d%d%d", &id, &fa, &mo, &k);
init(id);
if (~fa)
init(fa), merge(id, fa);
if (~mo)
init(mo), merge(id, mo);
for (int j = 1; j <= k; j++) {
int ch;
scanf("%d", &ch);
init(ch);
merge(id, ch);
}
int c, a;
scanf("%d%d", &c, &a);
int pid = find(id);
cnt_house[pid] += c;
area[pid] += a;
}
vector<Info> v;
for (int i = 0; i < N; i++)
if (p[i] == i) {
Info info;
info.ID = min_id[i];
info.M = cnt[i];
info.TOT_CNT = cnt_house[i];
info.TOT_AREA = area[i];
v.push_back(info);
}
sort(v.begin(), v.end(), [&](Info &x1, Info &x2) {
if (x1.TOT_AREA * x2.M != x2.TOT_AREA * x1.M) {
return x1.TOT_AREA * x2.M > x2.TOT_AREA * x1.M;
}
return x1.ID < x2.ID;
});
printf("%lu\n", v.size());
for (auto &info : v) {
printf("%04d %d %.3lf %.3lf\n", info.ID, info.M,
(double)info.TOT_CNT / info.M, (double)info.TOT_AREA / info.M);
}
}
时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间 O ( n ) O(n) O(n)。