L2-007 家庭房产
两个结构体数组,一个用来接收数据,另一个用来输出答案。
用 Union 函数来合并。由于要输出家庭成员的最小编号,所以,家庭成员的最小编号作为这个家庭集合的标志,p[find(a)] = find(b) ( find(a) > find(b))。
vis 数组用来标记所有出现过的人。people 来统计家庭人数。标记flag ,true 的数量,就是家庭的数量。
#include <iostream>
#include <algorithm>
using namespace std;
struct node_1
{
int id, fa, ma, num, area;
int cid[10];
} a[1010];
struct node_2
{
int id, people;
double num, area;
bool flag = false;
} ans[10000];
int n, k, cnt;
int p[10000];
bool vis[10000];
int find(int x)
{
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
void Union(int a, int b)
{
int pa = find(a), pb = find(b);
if (pa > pb) p[pa] = pb;
else if (pa < pb) p[pb] = pa;
}
bool cmp(node_2 a, node_2 b)
{
if (a.area != b.area) return a.area > b.area;
return a.id < b.id;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < 10000; i++) p[i] = i;
for (int i = 0; i < n; i++) {
scanf("%d%d%d%d", &a[i].id, &a[i].fa, &a[i].ma, &k);
vis[a[i].id] = true;
if (a[i].fa != -1) {
vis[a[i].fa] = true;
Union(a[i].fa, a[i].id);
}
if (a[i].ma != -1) {
vis[a[i].ma] = true;
Union(a[i].ma, a[i].id);
}
for (int j = 0; j < k; j++) {
scanf("%d", &a[i].cid[j]);
vis[a[i].cid[j]] = true;
Union(a[i].cid[j], a[i].id);
}
scanf("%d%d", &a[i].num, &a[i].area);
}
for (int i = 0; i < n; i++) {
int id = find(a[i].id);
ans[id].id = id;
ans[id].num += a[i].num;
ans[id].area += a[i].area;
ans[id].flag = true;
}
for (int i = 0; i < 10000; i++) {
if (vis[i]) ans[find(i)].people++;
if (ans[i].flag) cnt++;
}
for (int i = 0; i < 10000; i++) {
if (ans[i].flag) {
ans[i].num = ans[i].num * 1.0 / ans[i].people;
ans[i].area = ans[i].area * 1.0 / ans[i].people;
}
}
sort(ans, ans + 10000, 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;
}
这是我最开始的思路,有点复杂。遇到这种模拟题,要理清思路。
糟糕点:
(1)并没有将家庭成员的最小编号作为这个家庭集合的标志,导致后续还得求;
(2)map 来存集合标志,并用 cnt 对集合进行标号;
(3) 这个 ans 变长数组,压根没用呀,就是为了方便编号,用个 bool 数组也可以。
#include<bits/stdc++.h>
using namespace std;
int p[10000];
int visit[10000];
int num[10000];
int area[10000];
vector<int> ans[10005];
struct node{
int minId;
int people;
double num;
double area;
} res[10000];
int cmp1(node a, node b){
if(a.area != b.area)
return a.area > b.area;
return a.minId < b.minId;
}
void init(){
for(int i = 0; i < 10000; i++){
p[i] = i;
res[i].minId = 999999;
}
}
int find(int x){
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void Union(int x, int y){
p[find(y)] = find(x);
}
int main(){
init();
int n;
cin >> n;
for(int i = 0; i < n; i++){
int id, f, m, k;
cin >> id >> f >> m >> k;
visit[id] = 1;
if(f != -1){
Union(id, f);
visit[f] = 1;
}
if(m != -1){
visit[m] = 1;
Union(id, m);
}
for(int j = 0; j < k; j++){
int child;
cin >> child;
visit[child] = 1;
Union(id, child);
}
cin >> num[id] >> area[id];
}
int cnt = 0;
map<int, int> m;
for(int i = 0; i < 10000; i++){
if(visit[i] == 1){
int x = find(i);
if(ans[x].size() == 0){
cnt++;
m[x] = cnt;
}
ans[x].push_back(i);
int id = m[x];
res[id].area += area[i];
res[id].num += num[i];
res[id].minId = min(res[id].minId, i);
res[id].people++;
}
}
for (int i = 1; i <= cnt; i++) {
res[i].num = res[i].num * 1.0 / res[i].people;
res[i].area = res[i].area * 1.0 / res[i].people;
}
sort(res + 1, res + 1 + cnt, cmp1);
cout << cnt << endl;
for(int i = 1; i <= cnt; i++){
printf("%04d %d %.3f %.3f\n", res[i].minId, res[i].people, res[i].num, res[i].area);
}
}