pat1114 Family Property

题意:输入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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值