CCCC L2 007 家庭房产 并查集

最开始看到这个题,想不到只用并查集,在某一个如果同时又两个其他家庭包括的人怎么办,所有开了一个home类,想通过Home之间的合并解决这个问题,最后由于内容过于庞大而超时。

参考网上的思路用并查集可以实现这个过程

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


struct DATA {
    int id, fid, mid;
    int k;
    int sid[10];
    int n, s;
} d[1005];


struct ANS {
    int id, num, a1, a2;
    double b1, b2;
} ans[10005], res[10005];
int fa[10005];
bool vis[10005], has[10005];


bool cmp(ANS a, ANS b) {
    if(a.b2 == b.b2)
        return a.id < b.id;
    return a.b2 > b.b2;
}


void UF_set() {
    for(int i = 0; i <= 9999; i++)
        fa[i] = i;
}


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

/*不对某个人确定他的归属家族而是按家族合并*/
void Union(int a, int b) {
    int r1 = Find(a);
    int r2 = Find(b);
    if(r1 != r2) {
        if(r1 < r2)
            fa[r2] = r1;      
        else
            fa[r1] = r2;
    }
}


int main() {
    UF_set();
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d %d %d", &d[i].id, &d[i].fid, &d[i].mid);
        vis[d[i].id] = true;
        if(d[i].fid != -1) {
            vis[d[i].fid] = true;
            Union(d[i].id, d[i].fid);
        }
        if(d[i].mid != -1) {
            vis[d[i].mid] = true;
            Union(d[i].id, d[i].mid);
        }
        scanf("%d", &d[i].k);
        for(int j = 0; j < d[i].k; j++) {
            scanf("%d", &d[i].sid[j]);
            if(d[i].sid[j] != -1) {
                vis[d[i].sid[j]] = true;
                Union(d[i].id, d[i].sid[j]);
            }
        }
        scanf("%d %d", &d[i].n, &d[i].s);
    }
    for(int i = 0; i < n; i++) {
        int id = Find(d[i].id);
        ans[id].id = id;
        ans[id].a1 += d[i].n;
        ans[id].a2 += d[i].s;
    }
    for(int i = 0; i < 10000; i++)
        if(vis[i])
            ans[Find(i)].num ++;
    int cnt = 0;
    for(int i = 0; i < 10000; i++) {
        if(vis[i]) {
            int id = Find(i);
            if(!has[id]) {
                has[id] = true;
                res[cnt].b1 = (double)ans[id].a1 / (double)ans[id].num;
                res[cnt].b2 = (double)ans[id].a2 / (double)ans[id].num;
                res[cnt].id = id;
                res[cnt ++].num = ans[id].num;
            }
        }
    }
    sort(res, res + cnt, cmp);
    printf("%d\n", cnt);
    for(int i = 0; i < cnt; i++) {
        if(res[i].id < 10)
            printf("000%d %d %.3f %.3f\n", res[i].id, res[i].num, res[i].b1, res[i].b2);
        else if(res[i].id < 100)
            printf("00%d %d %.3f %.3f\n", res[i].id, res[i].num, res[i].b1, res[i].b2);
        else if(res[i].id < 1000)
            printf("0%d %d %.3f %.3f\n", res[i].id, res[i].num, res[i].b1, res[i].b2);
        else
            printf("%d %d %.3f %.3f\n", res[i].id, res[i].num, res[i].b1, res[i].b2);
    }
}

posted @ 2018-03-06 21:28  可爱如我  阅读(119)  评论(0编辑  收藏  举报