题目链接~https://www.patest.cn/contests/gplt/L2-007
分析:emmmmm,初次看题觉得很恶心,神烦这种输入一大堆乱七八糟数据还要求输出浮点数的题TAT
这次的并查集比较高明,合并的时候采取以num更小的为头目,也就是说,合并过程会把尽可能小的作为头目。。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+10;
struct Node{
int id;
int cnt,area;
}node[maxn];
struct Node2{
int id,num;
double area,cnt;
bool flag;
}res[maxn];
int father[maxn];
bool cmp(Node2 a, Node2 b){
if(a.flag && b.flag)
return a.id<b.id;
return a.flag>b.flag;
}
bool cmp2(Node2 a, Node2 b){
if(a.area == b.area){
return a.id < b.id;
}
return a.area>b.area;
}
void init(){
for(int i = 0; i<10000; i++){
father[i] = i;
}
}
int getF(int x){
int a = x;
while(x != father[x]){
x = father[x];
}
while(father[a] != x){
int tem = father[a];
father[a] = x;
a = tem;
}
return x;
}
void merge(int a, int b){
int fa = getF(a);
int fb = getF(b);
if(fa < fb){
father[fb] = fa;
}
else {
father[fa] = fb;
}
}
int main(){
init(); //初始化不能漏
int n,id,m,f,child,k,cnt,area;
cin>>n;
for(int i = 0; i<n; i++){
cin>>id>>m>>f;
node[i].id = id;
if(m != -1){
merge(id, m);
}
if(f != -1){
merge(id, f);
}
cin>>k;
for(int j = 0; j<k; j++){
cin>>child;
merge(id, child);
}
cin>>cnt>>area;
node[i].cnt=cnt;
node[i].area = area;
}
for(int i = 0; i<n; i++){
int cur = node[i].id;
int mm = getF(cur);
res[mm].id = mm;
res[mm].flag = true;
res[mm].area += node[i].area;
res[mm].cnt += node[i].cnt;
}
sort(res, res+maxn, cmp);
for(cnt = 0; cnt<maxn; cnt++){
if(res[cnt].flag == false)
break;
}
for(int i = 0; i<cnt; i++){
int total = 0;
id = res[i].id;
for(int j = 0; j<10000; j++){
if(getF(j) == id) total++;
}
res[i].num = total;
res[i].area /= (1.0*total);
}
cout<<cnt<<endl;
sort(res, res+cnt, cmp2);
for(int i = 0; i<cnt; i++){
printf("%04d %d %.3lf %.3f\n", res[i].id, res[i].num, res[i].cnt/(1.0*res[i].num), res[i].area);
}
return 0;
}