题意:输入n条信息,每一条表示一个人的id,父母id,孩子id,多少套房产,总面积。按照家庭平均房产从大到小输出一个家庭的最小id编号,人数,平局房产套数,平均房产面积。
思路:并查集维护家庭关系,最后扫一下,排个序就好。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <set>
using namespace std;
const int MAX_N = 100000;
const double EPS = 1e-8;
#define IsEqual(x, y) (fabs(x-y) <= EPS)
map<string, int> mp;
vector<string> v;
int id(string x) {
if (mp.count(x)) return mp[x];
v.push_back(x);
return mp[x] = v.size()-1;
}
int par[MAX_N];
void init(int n) {
for (int i = 0; i < n; i++) par[i] = i;
}
int find(int x) { if(x==par[x]) return x; return par[x] = find(par[x]); }
void uni(int x, int y) {
x = find(x); y = find(y);
if (x==y) return;
if (v[x] < v[y]) par[y] = x;
else par[x] = y;
}
int N, k, ct;
double tmpa;
char d[10], f[10], m[10], c[10];
map<int, int> cnt;
map<int, double> area;
map<int, int> ch;
map<int, double> marea;
map<int, int> num;
vector<int> ans;
set<int> cp;
bool cmp(int a, int b) {
double ava = marea[a] / ch[a];
double avb = marea[b] / ch[b];
return (IsEqual(ava, avb) && v[a] < v[b]) || (ava > avb);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d", &N);
init(MAX_N);
for (int i = 0; i < N; i++) {
scanf("%s %s %s %d", d, f, m, &k); cp.insert(id(d));
if (f[0] != '-') uni(id(d), id(f)), cp.insert(id(f));
if (m[0] != '-') uni(id(d), id(m)), cp.insert(id(m));
for (int j = 0; j < k; j++) {
scanf("%s", c);
cp.insert(id(c));
uni(id(d), id(c));
}
scanf("%d %lf", &ct, &tmpa);
cnt[id(d)] = ct; area[id(d)] = tmpa;
}
for (int i = 0; i < cp.size(); i++) {
ch[find(i)]++;
marea[find(i)] += area[i];
num[find(i)] += cnt[i];
}
for (auto it = ch.begin(); it != ch.end(); it++) ans.push_back(it->first);
sort(ans.begin(), ans.end(), cmp);
printf("%lu\n", ans.size());
for (int i = 0; i < ans.size(); i++) {
printf("%s %d %.3lf %.3lf\n", v[ans[i]].c_str(), ch[ans[i]], (double)num[ans[i]]/ch[ans[i]], marea[ans[i]]/ch[ans[i]]);
}
return 0;
}