题目大意:给出N个人的信息,信息中包括他的父母和子女的id(4位数),以及他名下的房产数量和面积。求出一共有多少个家庭,以及每个家庭的平均房产数和平均房产面积,并输出这个家庭中id最小的成员。
并查集问题,一开始看到 N<=1000,id是四位数,考虑能不能通过对应来缩小范围,但是这是不可以的,因为包括他的父母和子女在内,远超过N个人。所以还是只能从0遍历到9999, 输入的同时要记录该编号出现过,否则从0遍历到9999会遍历到没出现的编号。之后就是统计每个家庭的根节点的房产数量和面积,注意在遍历时只有根节点与当前节点不同才能加上他的房产,否则会造成根节点的重复计算。最后还要记录每个根节点对应的最小id。虽然逻辑并不复杂,但是写起来还是一堆bug。
AC代码:
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN = 10010;
int parent[MAXN];
int findParent(int p)
{
while(p != parent[p])
{
parent[p] = parent[parent[p]];
p = parent[p];
}
return p;
}
void unionElement(int a, int b)
{
int aRoot = findParent(a);
int bRoot = findParent(b);
parent[aRoot] = bRoot;
}
struct family
{
int smallestId;
int cnt;
int totalSets;
int totalAreas;
double avgSets;
double avgAreas;
family(int smallestId, int cnt, int totalSets, int totalAreas): smallestId(smallestId), cnt(cnt), totalSets(totalSets), totalAreas(totalAreas), avgSets(totalSets * 1.0 / cnt), avgAreas(totalAreas * 1.0 / cnt){};
bool operator <(const family& other)
{
if(this->avgAreas != other.avgAreas) return this->avgAreas > other.avgAreas;
else return this->smallestId < other.smallestId;
}
};
int main()
{
int N;
scanf("%d\n", &N);
int sets[MAXN] = {0};
int areas[MAXN] = {0};
int roots[MAXN] = {0};
int smallestId[MAXN] = {0};
bool hasAppeared[MAXN] = {0};
fill(smallestId, smallestId + MAXN, 1e5);
for (int i = 0; i < MAXN; ++i)
parent[i] = i;
for (int i = 0; i < N; ++i)
{
int name, father, mother, childNum;
scanf("%d%d%d%d", &name, &father, &mother, &childNum);
hasAppeared[name] = true;
if(father > -1)
{
hasAppeared[father] = true;
unionElement(name, father);
}
if(mother > -1)
{
hasAppeared[mother] = true;
if(father > -1) unionElement(mother, father);
else unionElement(name, mother);
}
for (int j = 0; j < childNum; ++j)
{
int child;
scanf("%d", &child);
hasAppeared[child] = true;
unionElement(child, name);
}
scanf("%d%d", &sets[name], &areas[name]);
}
for (int i = 0; i < MAXN; ++i)
{
if(hasAppeared[i])
{
int root = findParent(i);
roots[root]++;
if(root != i) sets[root] += sets[i];
if(root != i) areas[root] += areas[i];
if(smallestId[root] > i) smallestId[root] = i;
}
}
vector<family> v;
for (int i = 0; i < MAXN; ++i)
if(roots[i] > 0) v.push_back(family(smallestId[i], roots[i], sets[i], areas[i]));
sort(v.begin(), v.end());
printf("%d\n", v.size());
for (int i = 0; i < v.size(); ++i)
printf("%04d %d %.3f %.3f\n", v[i].smallestId, v[i].cnt, v[i].avgSets, v[i].avgAreas);
return 0;
}