一、技术总结
- 这题考查内容为并查集,核心是用一个数组存储当前结点的父节点编号,操作有初始化、查找、合并。
- 题意首先理解一下,题目意思是给出N行,然后每行中首先给出自己的ID号、然后是父亲ID、再是母亲ID,如果父亲跟母亲已经去世,该ID好给出为-1,然后再给数字num,代表给人的孩子数,后面跟上num个孩子的ID号,最后是这个人拥有房子的数量和总面积。最后要求是如果是有直接或间接关系的归为一个家庭,然后求出该家庭的平均房子数量,和平均面积都保留三位小数。输出结果按照平均面积降序输出,如果一样则按各自家庭中最小ID号升序输出。
- 首先应该定义一个father数组用于并查集操作,同时设置一个visit数组用于存储所有有效结点。在其实在读取每行的时候就可以进行合并操作,这里有一点需要注意一下,因为题目要求是给出每个家庭成员中的最小ID号来代表该家庭,所以合并时,应该直接将ID号较小的作为父节点。
- 我们设置Data结构体用于存储每行的数据,用这是node结构体用于存储将要输出的家庭,里面包含ID号、家庭人数、平均房子数量、平均住房面积、还有标志位flag用于查看该ID号是否为有效家庭,即用于统计家庭数量。通过遍历data中的每行,最小家庭号直接用查找函数查找有其父节点,同时也加上该成员的住房面积和房子数量。而成员数量通过之前的visit数组遍历,有效结点分别归属于哪一个家庭。这时统计cnt也就是家庭数量。
- 最后统计完成后,计算出平均住房面积、数量,再使用sort函数排序,最后输出结果。
二、参考代码
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 1010;
const int MAXN = 10000;
struct Data{
int id, fid, mid;
int num, area;
int kid[10];
}data[MAXV];
struct node{
int id, people;
double num, area;
bool flag = false;
}ans[MAXN];
bool visit[MAXN];
int father[MAXN];
int findFather(int x){
int a = x;
while(x != father[x]){
x = father[x];
}
while(a != father[a]){
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void Union(int a, int b){
int faA = findFather(a);
int faB = findFather(b);
if(faA > faB){
father[faA] = faB;
}else if(faA < faB){
father[faB] = faA;
}
}
bool cmp(node a, node b){
if(a.area != b.area){
return a.area > b.area;
}else{
return a.id < b.id;
}
}
int main(){
int n, k, cnt = 0;
scanf("%d", &n);
for(int i = 0; i < 10000; i++){
father[i] = i;
}
for(int i = 0; i < n; i++){
scanf("%d %d %d %d", &data[i].id, &data[i].fid, &data[i].mid, &k);
visit[data[i].id] = true;
if(data[i].fid != -1){
visit[data[i].fid] = true;
Union(data[i].id, data[i].fid);
}
if(data[i].mid != -1){
visit[data[i].mid] = true;
Union(data[i].id, data[i].mid);
}
for(int j = 0; j < k; j++){
scanf("%d", &data[i].kid[j]);
visit[data[i].kid[j]] = true;
Union(data[i].id, data[i].kid[j]);
}
scanf("%d %d", &data[i].num, &data[i].area);
}
for(int i = 0; i < n; i++){
int id = findFather(data[i].id);
ans[id].id = id;
ans[id].num += data[i].num;
ans[id].area += data[i].area;
ans[id].flag = true;
}
for(int i = 0; i < MAXN; i++){
if(visit[i]){
int id = findFather(i);
ans[id].people++;
}
if(ans[i].flag){
cnt++;
}
}
for(int i = 0; i < MAXN; i++){
if(ans[i].flag){
ans[i].num = (double)(ans[i].num * 1.0 / ans[i].people);
ans[i].area = (double)(ans[i].area * 1.0 / ans[i].people);
}
}
sort(ans, ans+MAXN, cmp);
printf("%d\n", cnt);
for(int i = 0; i < cnt; i++){
printf("%04d %d %.3f %.3f\n", ans[i].id, ans[i].people, ans[i].num, ans[i].area);
}
return 0;
}