思路:
考察的是并查集和结构体排序,再读入数据的时候按照编号大小,将编号小的树合并到编号大的树上,然后遍历所有数据,将家庭一样的结构体放在一起(放在a数组里),并跟新家庭的属性信息,最后排序输出。
AC 代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5,INF = 0x3f3f3f3f;
struct home {
int my_id,fa_id,mo_id;
int kid_num;
vector<int> kid;
int sum,area;
}h[1050];
struct node {
int id;
int num;
double fnum,sarea;
bool flag;
}a[N];
vector<node> ans;
int fa[N],n;
bool vst[N];
int find(int x) {
if(fa[x] != x)
fa[x] = find(fa[x]);
return fa[x];
}
void merg(int x,int y) {
int fx = find(x),fy = find(y);
if(fx < fy) {
fa[fy] = fx;
}
else
fa[fx] = fy;
}
bool cmp(node a,node b) {
if(a.sarea / a.num == b.sarea / b.num)
return a.id < b.id;
else return a.sarea / a.num > b.sarea / b.num;
}
int main() {
for(int i = 0; i <= N; i ++)
fa[i] = i;
cin>>n;
for(int i = 0; i < n; i ++) {
// 读入数据
cin>>h[i].my_id>>h[i].fa_id>>h[i].mo_id;
cin>>h[i].kid_num;
for(int j = 0; j < h[i].kid_num; j ++) {
int tmp;
cin>>tmp;
h[i].kid.push_back(tmp);
}
cin>>h[i].sum>>h[i].area;
// 合并
if(h[i].fa_id != -1) {
merg(h[i].my_id,h[i].fa_id);
}
if(h[i].mo_id != -1) {
merg(h[i].my_id,h[i].mo_id);
}
if(h[i].kid_num != 0) {
for(auto id : h[i].kid) {
merg(h[i].my_id,id);
}
}
//cout<<h[i].kid_num<<find(h[i].my_id)<<endl;
}
// 记录
for(int i = 0; i < n; i ++) {
int f = find(h[i].my_id);
a[f].flag = 1;
a[f].id = f;
a[f].fnum += h[i].sum;
a[f].sarea += h[i].area;
}
for(int i = 0; i < N; i ++) {
int f = find(i);
if(!vst[i]) {
a[f].num ++;
vst[i] = true;
}
}
for(int i = 0; i < N; i ++) {
int f = find(i);
if(a[f].flag) {
ans.push_back(a[f]);
a[f].flag = 0;
}
}
sort(ans.begin(),ans.end(),cmp);
cout<<ans.size()<<endl;
for(auto x : ans) {
printf("%04d %d %.3f %.3f\n",x.id,x.num,x.fnum/x.num,x.sarea/x.num);
}
return 0;
}