【并查集】PAT甲级 1114 Family Property

1114 Family Property

解题思路

对每个有关系的 id 进行并查集的合并操作。合并时注意处理面积、房的套数。

参考代码

#include<stdio.h>
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<deque>
#include<map>
#include<unordered_map>
#include<set>
#include<stack>
//#define LOCAL  //提交时一定注释
#define VI vector<int>
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
typedef long long LL;
typedef double db;
const int inf = 0x3f3f3f3f;
const LL INF = 1e18;
const int N = 1e4 + 10;

inline int readint() {int x; scanf("%d", &x); return x;}

struct node{
    int id;  //最小的id
    set<int> st;  //存家庭成员的id
    int a, s;  //面积,房的数量
    db aa, as;
    node() {id = inf, a = s = 0;}
    bool operator < (const node& y) const{
        if (aa != y.aa) return aa > y.aa;
        return id < y.id;
    }
}s[N];
int fa[N], vis[N];

void merge(int u, int v) {
    if (u == v) return;
    fa[u] = v;
    s[v].id = min(s[v].id, s[u].id);
    s[v].a += s[u].a;
    s[v].s += s[u].s;
    for(auto it = s[u].st.begin(); it != s[u].st.end(); ++it) {
        s[v].st.insert(*it);
    }
}

int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void init() {
    for(int i = 0; i < N; ++i) {
        fa[i] = i;
        s[i].st.insert(i);
        s[i].id = i;
    }
}
int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
//   freopen("output.txt", "w", stdout);
#endif
    int t = readint();
    init();
    int k;
    while (t--) {
        k = readint();
        vis[k] = true;
        int rt = find(k);
        for(int i = 1; i <= 2; ++i) {
            k = readint();
            vis[k] = true;
            if (k != -1)
                merge(find(k), rt);
        }
        int num = readint();
        for(int i = 1; i <= num; ++i) {
            k = readint();
            vis[k] = true;
            merge(find(k), rt);
        }
        s[rt].s += readint();
        s[rt].a += readint();
    }
    vector<node> ans;
    for(int i = 0; i < N; ++i) {
        if (vis[i] && fa[i] == i) {
//            cout << "rt:" << i << " a:" << s[i].a << " sz:" << s[i].st.size();
            int sz = s[i].st.size();
            s[i].aa = 1.0 * s[i].a / sz;
//            cout << "aa: " << s[i].aa << endl;
            s[i].as = 1.0 * s[i].s / sz;
            ans.push_back(s[i]);
        }
    }
    sort(ans.begin(), ans.end());
    printf("%d\n", (int)ans.size());
    for(auto m : ans) {
        printf("%04d %d %.3f %.3f\n", m.id, m.st.size(), m.as, m.aa);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值