1

题目大意

给定一个人的家庭成员及其房产信息,需要知道每一个家庭的人数,平均占地面积和房产数目。

算法思路

这是一道常规的并查集应用题目,我们首先使用families数组保存所有的输入集,并在输入的时候记录哪些是输入的成员(使用visited记录),并且合并那些是一家人的成员,这样就将所有成员都进行了归类在各自的家庭,然后计算每一个家庭的占地总面积和总房产数目,并且使用flag标记当前家庭(在[0,10000]中有意义的家庭),然后在[0,10000]的所有人中统计所有的家庭成员数目(visited[i]=true的就是)和家庭数目(flag为true的人代表一个家庭),最后计算房子的平均面积和数目。

注意点

  • 1、在输入的时候families的下标是从0开始到n-1结束,这样方便遍历输入的成员并进行信息计算
  • 2、计算房子的平均面积和数目的时候,得使用总共的信息total_*除以家庭人数,因为该计算过程会执行多次。

提交结果

image.png

AC代码

#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

struct Family {
    int ID;
    int father;
    int mother;
    vector<int> children;
    int estate;
    int area;
} families[1001];

// 存储结果集
struct Node {
    int ID;
    int total_number;
    double Avg_sets;
    double Avg_area;
    int total_sets;
    int total_area;
    bool flag;// 标记当前家庭
} nodes[10000];

bool cmp(const Node &a, const Node &b) {
    return a.Avg_area != b.Avg_area ? a.Avg_area > b.Avg_area : a.ID < b.ID;
}

// 统计在[0,10000]中哪些是存在的成员
bool visited[10000];

// 记录每一个人的祖先(可能不在输入中)
int father[10000];

// 找到x的祖先,这里采用了压缩路径的方式
int findFather(int x) {
    int a = x;
    while (x != father[x]) {
        x = father[x];
    }
    while (a != father[a]) {
        int z = father[a];
        father[a] = x;
        a = z;
    }
    return x;
}

void Union(int a, int b) {
    int fa = findFather(a);
    int fb = findFather(b);
    if (fa < fb) {
        father[fb] = fa;
    } else {
        father[fa] = fb;
    }
}

int main() {
    for (int i = 0; i < 10000; ++i) {
        father[i] = i;
    }
    int n;
    scanf("%d", &n);
    Family member;
    int k;
    for (int i = 0; i < n; ++i) {
        scanf("%d %d %d %d", &member.ID, &member.father, &member.mother, &k);
        int child;
        for (int j = 0; j < k; ++j) {
            scanf("%d", &child);
            member.children.push_back(child);
            visited[child] = true;
            Union(member.ID, child);
        }
        scanf("%d %d", &member.estate, &member.area);
        families[i] = member;
        visited[member.ID] = true;
        if (member.father != -1) {
            visited[member.father] = true;
            Union(member.ID, member.father);
        }
        if (member.mother != -1) {
            visited[member.mother] = true;
            Union(member.ID, member.mother);
        }
    }
    // 将所有归类的家庭进行计算相关信息
    for (int i = 0; i < n; ++i) {
        int id = findFather(families[i].ID);
        nodes[id].ID = id;
        nodes[id].total_area += families[i].area;
        nodes[id].total_sets += families[i].estate;
        nodes[id].flag = true;
    }
    int num = 0;
    // 统计家庭成员人数和家庭数目
    for (int i = 0; i < 10000; ++i) {
        if (visited[i]) {
            int id = findFather(i);
            ++nodes[id].total_number;
        }
        if (nodes[i].flag) {
            ++num;
        }
    }
    // 计算房子的平均面积和平均数目
    for (int i = 0; i < 10000; ++i) {
        if (visited[i]) {
            int id = findFather(i);
            nodes[id].Avg_area = nodes[id].total_area*1.0/nodes[id].total_number;
            nodes[id].Avg_sets = nodes[id].total_sets*1.0/nodes[id].total_number;
        }
    }
    printf("%d\n", num);
    sort(nodes,nodes+10000,cmp);
    for(int i=0;i<num;++i){
        printf("%04d %d %.3f %.3f\n",nodes[i].ID,nodes[i].total_number,nodes[i].Avg_sets,nodes[i].Avg_area);
    }
    return 0;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得