思路:一看什么几个家庭什么的,就想到了用并查集去维护家庭关系。输入的处理有点麻烦,题目中说了每个人的编号是一个不重复的四位数字,所以我们可以借鉴 PAT ~ L2-002. 链表去重 (思路 + 模拟)这道题目,直接把数组下标就作为是哪个人。
每个人需要记录它属于哪个家庭(即编号最小的人的编号),家庭总人数,家庭总房产套数,家庭总房产面积。因为人均过程中有精度损失,所以先保存总的。合并过程中注意要合并到编号小的上面,且家庭总人数,家庭总房产套数,家庭总房产面积也都要进行累加。
初始化时使家庭总人数=0,如果关系涉及到该人时,他的家庭总人数为0,那么就变为1,然后在进行合并。
最终,自己的编号==自己的父节点的,且家庭人数不为0,那么就是一个家庭。然后把这个信息copy到另一个ans数组里,
对ans数组按要求排序输出即可。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10005;
int n;
struct Node
{
int id, cnt;//家庭成员的最小编号 家庭人口数
double num, area;//总房产套数 总房产面积
}a[MAXN], ans[MAXN];
void init()
{
for (int i = 0; i < MAXN; i++)
{
a[i].id = i; a[i].cnt = 0;
a[i].num = 0.0; a[i].area = 0.0;
}
}
int Find(int x)
{
if (a[x].id == x) return x;
a[x].id = Find(a[x].id);
return a[x].id;
}
void Union(int x, int y)
{
int root1 = min(Find(x), Find(y)), root2 = max(Find(x), Find(y));
//注意编号小的做根
if (root1 != root2)
{
a[root1].cnt += a[root2].cnt;
a[root1].num += a[root2].num;
a[root1].area += a[root2].area;
a[root2].id = root1;
}
}
bool cmp(Node a, Node b)
{
if (a.area / a.cnt != b.area / b.cnt)
return a.area / (double)a.cnt > b.area / (double)b.cnt;
return a.id < b.id;
}
int main()
{
init();
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
int id, father, mather, k, child, num, area;
scanf("%d%d%d%d", &id, &father, &mather, &k);
if (a[id].cnt == 0) a[id].cnt = 1;
if (father != -1)
{
if (a[father].cnt == 0) a[father].cnt = 1;
Union(id, father);
}
if (mather != -1)
{
if (a[mather].cnt == 0) a[mather].cnt = 1;
Union(id, mather);
}
while (k--)
{
scanf("%d", &child);
if (a[child].cnt == 0) a[child].cnt = 1;
Union(id, child);
}
scanf("%d%d", &num, &area);
a[Find(id)].num += num;
a[Find(id)].area += area;
}
int cnt = 0;//家庭数
for (int i = 0; i < MAXN; i++)
{
if (a[i].id == i && a[i].cnt != 0)
{
ans[cnt++] = a[i];
}
}
sort(ans, ans + cnt, cmp);
printf("%d\n", cnt);
for (int i = 0; i < cnt; i++)
{
printf("%04d %d ", ans[i].id, ans[i].cnt);
printf("%.3f %.3f\n", ans[i].num / (double)ans[i].cnt, ans[i].area / (double)ans[i].cnt);
}
return 0;
}
/*
10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100
*/