1114 Family Property

题目描述
知识点: 并查集
思路: 本题为并查集的一道扩展版,需要维护额外的信息。细心点即可。需要开辟的维护数组有:集合最小的id,集合中的元素个数,集合中的面积总和,集合中的房子数量。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 10010;
double num_set[N],num_family[N],num_area[N],small_id[N];
int p[N],n;
bool v[N];
int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}
struct Res{
    int id,family_cnt;
    double avg_set,avg_area;
    bool operator < (const Res r) const{
        if(abs(avg_area - r.avg_area) > 1e-5) return avg_area > r.avg_area;
        return id < r.id;
    } 
};
void merge_family(int x,int y){
    v[x] = 1,v[y] = 1;
    x = find(x);
    y = find(y);
    if(x != y){
        num_set[p[y]] += num_set[p[x]];
        num_family[p[y]] += num_family[p[x]];     
        num_area[p[y]] += num_area[p[x]];     
        small_id[p[y]] = min(small_id[p[y]],small_id[p[x]]);
        p[x] = p[y];        
    }
}
int main(){
    for(int i = 0;i < N;i++){
        p[i] = i;
        num_family[i] = 1;
        small_id[i] = i;
    }
    cin>>n;
    while(n--){
        vector<int> children;
        int id,p1,p2,k,child;
        double sets,total_area;
        cin>>id>>p1>>p2>>k;
        for(int i = 0;i < k;i++) {
            int c;
            cin>>c;
            children.push_back(c);
        }
        cin>>sets>>total_area;
        int x = find(id);
        v[id] = 1;
        num_set[p[x]] += sets;
        num_area[p[x]] += total_area;
        if(p1 != -1) merge_family(id,p1);
        if(p2 != -1) merge_family(id,p2);
        for(int i = 0;i < children.size();i++)
            merge_family(id,children[i]);
    }
    vector<Res> res;
    for(int i = 0;i < 10000;i++){
        if(v[i] && p[find(i)] == i){
            res.push_back({small_id[i],num_family[i],(double)num_set[i]/num_family[i],(double)num_area[i]/num_family[i]});
        }
    }
    sort(res.begin(),res.end());
    cout<<res.size()<<endl;
    for(auto &i : res){
        printf("%04d %d %.3lf %.3lf\n",i.id,i.family_cnt,i.avg_set,i.avg_area);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值