• PAT A1114 Family Property [并查集]


    题目描述

    链接
    给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积。其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

    分析

    • 维护的是亲属关系,只要是有亲属关系,则属于这个集合,不用管这是是父母还是孩子,反正有亲属关系就好了
      • (fa[i]=i) 就算事先还没有明确元素个数,也可以先初始化了再说,也就是循环到(maxn)
      • 然后输入一个亲属结点(父母孩子),就执行(merge(id, xxx))
    • (data)结构体数组接收数据,同时进行(merge)操作
    • (ans)结构体数组统计信息,里面有很多坑,看代码吧
      • 因为之前是循环到(maxn),所以用了(vis)数组来标记有效结点
      • 同时加(flag)变量标记根结点
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 1e5;
    
    int fa[maxn];
    bool vis[maxn];
    int n,k,cnt;
    
    struct Data{
        int id, fid, mid, num, area, cid[10];
    }data[1005];
    
    struct node {
        int id, cnt;
        double num, area;
        bool flag;
    }ans[maxn];
    
    int find(int x){
        int r = x;
        while(x != fa[x]) x = fa[x];
        while(r != fa[r]){
            int t = r;
            r = fa[r];
            fa[t] = x;
        }
        return x;
    }
    
    void merge(int x, int y){
        int fx = find(x);
        int fy = find(y);
        if(fx!=fy) fa[max(fx,fy)] = min(fx,fy); //较小编号的作为祖先
    }
    
    int cmp(node a, node b) {
        if(a.area != b.area) return a.area > b.area;
        return a.id < b.id;
    }
    
    int main() {
        int n, k, cnt = 0;
        scanf("%d", &n);
        for(int i = 0; i < maxn; i++) fa[i] = i; //当结点数未定时也可以初始化
        //用data结构体保存读入的数据,注意data的大小只有n,不是maxn
        for(int i = 0; i < n; i++) {
            scanf("%d %d %d %d", &data[i].id, &data[i].fid, &data[i].mid, &k);
            vis[data[i].id] = true;
            if(data[i].fid != -1) {
                vis[data[i].fid] = true;
                merge(data[i].fid, data[i].id);
            }
            if(data[i].mid != -1) {
                vis[data[i].mid] = true;
                merge(data[i].mid, data[i].id);
            }
            for(int j = 0; j < k; j++) {
                scanf("%d", &data[i].cid[j]);
                vis[data[i].cid[j]] = true;
                merge(data[i].cid[j], data[i].id);
            }
            scanf("%d %d", &data[i].num, &data[i].area);
        }
        //用ans结构体统计信息,只保存根节点
        for(int i = 0; i < n; i++) {
            int id = find(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 < maxn; i++) {
            if(vis[i])
                ans[find(i)].cnt++;
            if(ans[i].flag)
                cnt++;
        }
        //计算平均
        for(int i = 0; i < maxn; i++) {
            if(ans[i].flag) {
                ans[i].num = (double)(ans[i].num * 1.0 / ans[i].cnt);
                ans[i].area = (double)(ans[i].area * 1.0 / ans[i].cnt);
            }
        }
        sort(ans, ans + maxn, cmp);
        printf("%d
    ", cnt);
        for(int i = 0; i < cnt; i++)
            printf("%04d %d %.3f %.3f
    ", ans[i].id, ans[i].cnt, ans[i].num, ans[i].area);
        return 0;
    }
    
    
    
  • 相关阅读:
    javac 命令行使用总结
    电脑右键菜单的编辑(注册表操作)
    C++ —— 类模板的分离式编译
    命令行学习备份
    浏览器老是自动跳出广告垃圾网页
    SQL 事务
    Python中MySQL插入数据
    Python给数字前固定位数加零
    selenium+python3 鼠标事件
    mysql与mongodb命令对比
  • 原文地址:https://www.cnblogs.com/doragd/p/11278479.html
Copyright © 2020-2023  润新知