题目大意
给定一个人的家庭成员及其房产信息,需要知道每一个家庭的人数,平均占地面积和房产数目。
算法思路
这是一道常规的并查集应用题目,我们首先使用families数组保存所有的输入集,并在输入的时候记录哪些是输入的成员(使用visited记录),并且合并那些是一家人的成员,这样就将所有成员都进行了归类在各自的家庭,然后计算每一个家庭的占地总面积和总房产数目,并且使用flag标记当前家庭(在[0,10000]中有意义的家庭),然后在[0,10000]的所有人中统计所有的家庭成员数目(visited[i]=true的就是)和家庭数目(flag为true的人代表一个家庭),最后计算房子的平均面积和数目。
注意点
- 1、在输入的时候families的下标是从0开始到n-1结束,这样方便遍历输入的成员并进行信息计算
- 2、计算房子的平均面积和数目的时候,得使用总共的信息total_*除以家庭人数,因为该计算过程会执行多次。
提交结果
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;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。