- Problem:
https://pintia.cn/problem-sets/994805046380707840/problems/994805068539215872 - tags:
并查集 细节 - Mean:
如题 - Solution
读入的时候就做并查集的查找,并把所有人都修改为最小的那个.然后再遍历一次记录数据,最后排序输出 - Mistakes
1.并查集操作要find(i),例如修改祖先,不能是fa[x]=Min,要,fa[find(x)]=Min.因为这样才能整体修改,虽然道理很简单,但是经常会写忘记掉.
2.数据读入的时候,先读入ID,后面按ID填.一开始顺手按I填了,最后数据全是0,debug半天 - Grains
代码写的太丑了,主要是这题恶心的不行.不想改了.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N =1e5+10;
const ll mod=1e9;
int n,fa[10003];
struct node{
int id,f,m,kids,house;
int k[10],area;
}p[N];
struct Node{
int id,peo;
double home,area;
bool operator<(const Node b){
if(area==b.area) return id<b.id;
return area > b.area;
}
}P[10003];
int find(int x){
if(x==-1 || fa[x]==-1) return x;
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
int vis[10003];
int home[10004];
int area[10004];
int main(){
cin>>n;
memset(fa,-1,sizeof(int)*1e4+2);
for(int i=1;i<=n;i++){
int Min = 1e7+3,T;
cin>>T;
p[T].id = T;
cin>>p[T].f>>p[T].m>>p[T].kids;
for(int j=0;j<p[T].kids;j++){
cin>>p[T].k[j];
Min = min(Min,find(p[T].k[j]));
}
cin>>p[T].house>>p[T].area;
if(find(p[T].id)!=-1) Min = min(Min,find(p[T].id));
if(find(p[T].f)!=-1) Min = min(Min,find(p[T].f));
if(find(p[T].m)!=-1) Min = min(Min,find(p[T].m));
fa[find(p[T].id)]=fa[find(p[T].f)]=fa[find(p[T].m)] = find(Min);
for(int j=0;j<p[T].kids;j++) fa[find(p[T].k[j])] = find(Min);
}
int cnt = 0;
for(int i=0;i<10000;i++)
if(fa[i]!=-1){
home[find(i)]+=p[i].house;
area[find(i)]+=p[i].area;
vis[find(i)]++;
}
for(int i=0;i<10000;i++){
if(vis[i]){
P[cnt].id = i;
P[cnt].peo = vis[i];
P[cnt].area = area[i]*1.0/(vis[i]*1.0);
P[cnt].home = home[i]*1.0/(vis[i]*1.0);
cnt++;
}
}
cout<<cnt<<endl;
sort(P,P+cnt);
for(int i=0;i<cnt;i++){
printf("%04d %d %.3lf %.3lf\n",P[i].id,P[i].peo,P[i].home,P[i].area);
}
}