L2 - 007 家庭房产

本题传送门

解题思路

这题需要存很多信息,显然要用结构体,同时,使用结构体也方便排序。

要敢于用结构体,尤其是在天梯赛

同时还需要并查集,又因为题目要求输出最小编号,所以我们可以令最小编号为祖宗 。不妨再用个结构体存答案,家庭祖宗编号,以及人数,房产面积

只要保证思维不乱,还是能够写出来的,不过代码很长

把父母合并标记一下,最后统计每个家庭人数的时候,如果visit为true ,家庭人数加 1 。
从头到尾遍历一下,找到每个人的祖宗,然后让祖宗的结果结构体的数据加上每个人的财产,最后就是家庭的具体情况

#include<cstdio>
#include<algorithm>
using namespace std;

struct DATA {
    int id, fid, mid, num, area;
    int cid[10];
} d[1005]; // data 已换成 d

struct node {
    int id, people;
    double num, area;
    bool flag = false;
} ans[10005]; // 整合为家庭结构

int father[10005];
bool visit[10005];

int find(int x) {
    if (father[x] != x) {
        father[x] = find(father[x]);
    }
    return father[x];
}

// 编号小的为根
void Union(int a, int b) {
    int faA = find(a);
    int faB = find(b);
    if (faA > faB) father[faA] = faB;
    else if (faA < faB) father[faB] = faA;
}

bool cmpl(node a, node b) {
    // 核心补丁:先把 flag 为 false 的幽灵数据沉底
    // if (a.flag != b.flag) return a.flag > b.flag;
    // 再按面积降序
    if (a.area != b.area) return a.area > b.area;
    // 最后按 ID 升序
    return a.id < b.id;
}

int main() {
    int n, k, cnt = 0;
    if (scanf("%d", &n) == EOF) return 0;

    for (int i = 0; i < 10000; i++) father[i] = i;

    for (int i = 0; i < n; i++) {
        // data 全部替换为 d
        scanf("%d %d %d %d", &d[i].id, &d[i].fid, &d[i].mid, &k);
        visit[d[i].id] = true;
        if (d[i].fid != -1) {
            visit[d[i].fid] = true;
            Union(d[i].fid, d[i].id);
        }
        if (d[i].mid != -1) {
            visit[d[i].mid] = true;
            Union(d[i].mid, d[i].id);
        }
        for (int j = 0; j < k; j++) {
            scanf("%d", &d[i].cid[j]);
            visit[d[i].cid[j]] = true;
            Union(d[i].cid[j], d[i].id);
        }
        scanf("%d %d", &d[i].num, &d[i].area);
    }

    // 统计家庭总房产和面积
    for (int i = 0; i < n; i++) {
        int id = find(d[i].id);
        ans[id].id = id;
        ans[id].num += d[i].num;
        ans[id].area += d[i].area;
        ans[id].flag = true;
    }

    // 统计家庭总人数和有效家庭总数
    cnt = 0; // 重置 cnt
    for (int i = 0; i < 10000; i++) {
        if (visit[i]) ans[find(i)].people++;
        if (ans[i].flag) cnt++;
    }

    // 计算平均值
    for (int i = 0; i < 10000; i++) {
        if (ans[i].flag) {
            ans[i].num = ans[i].num * 1.0 / ans[i].people;
            ans[i].area = ans[i].area * 1.0 / ans[i].people;
        }
    }

    // 排序:前 cnt 个就是我们要的
    sort(ans, ans + 10000, cmpl);

    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;
}
posted @ 2026-03-14 19:25  shuiwangrenjia  阅读(1)  评论(0)    收藏  举报