PAT【甲级】1114

题目链接:PAT【甲级】1114
题目简述:给定每个⼈人的家庭成员和其⾃自⼰己名下的房产,要求统计出每个家庭的⼈人⼝口数、⼈人均房产⾯积及房产套数。家庭信息⾸先按⼈均⾯积降序输出,若有并列,则按成员编号的升序输出。

#include<bits/stdc++.h>
using namespace std;

unordered_map<int, int> areas, sets, members;
int father[10000], exist[10000], minID[10000];
struct node{
    int id, Count;
    double avgs, avga;
    bool operator < (const node& p){
        return avga == p.avga ? id < p.id : avga > p.avga;//这边比较还有待确定是否正确
    }
};

int findFather(int a){
    int x = a;
    while(x != father[x]) x = father[x];
    while(a != father[a]){//路径压缩【这边压不压不影响】
        int t = father[a];
        father[a] = x;
        a = t;
    }
    return x;
}

void Union(int a, int b){
    int x1 = findFather(a), x2 = findFather(b);
    if(x1 != x2) father[x2] = x1;
}

int main(){
    int n, id, fid, mid, k, cid, m, a;
    cin >> n;
    for (int i = 0; i < 10000; i++)
        father[i] = i;
    for (int i = 0; i < n; i++){
        cin >> id >> fid >> mid >> k;
        exist[id] = 1;//标记出现过
        if(fid != -1){//合并树
            Union(id, fid);
            exist[fid] = 1;
        } 
        if(mid != -1){
            Union(id, mid);
            exist[mid] = 1;
        } 
        for (int j = 0; j < k;j++){
            cin >> cid;
            Union(id, cid);
            exist[cid] = 1;
        }
        cin >> m >> a;
        // areas[findFather(id)] += a;
        // sets[findFather(id)] += m;
        areas[id] = a;//记录房产信息
        sets[id] = m;
    }
    fill(minID, minID + 10000, -1);//初始化
    for (int i = 0; i < 10000;i++){
        if(exist[i] == 1){//如果当前编号存在
            int root = findFather(i);
            members[root]++;
            if(root != i){//避免重复累加
                areas[root] += areas[i];
                sets[root] += sets[i];
            }
            if(minID[root] > i || minID[root] == -1){//更新每个家庭的最小编号成员
                minID[root] = i;
            }
        }
    }
    vector<node> v;
    for (auto i = members.begin(); i != members.end();i++)
        v.push_back({minID[i->first], members[i->first], 1.0 * sets[i->first] / members[i->first], 1.0 * areas[i->first] / members[i->first]});
    sort(v.begin(), v.end());
    cout << v.size() << endl;
    for (int i = 0; i < v.size();i++)
        printf("%04d %d %.3f %.3f\n", v[i].id, v[i].Count, v[i].avgs, v[i].avga);
    return 0;
}

这个题目有两个关键点,分享一下:

  1. 不能够在数据输入的同时,去像这样来记录房产信息。
// areas[findFather(id)] += a;
// sets[findFather(id)] += m;

因为根节点时会变的。当数据不断的输入时,我们无法保证根节点还是原来的根节点,所以这里会出错的。必须先暂存下来,在后续的处理中来进行处理。

  1. 编号问题。有可能编号是为0的,所以我这边使用了数组,默认值为-1来规避掉这个问题。平时出于便利【其实也就那样】用unordered_map,这里边不好用了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值