解题思路
我们可以枚举平均数,然后根据
(
a
i
−
a
ˉ
)
2
(a_i-\bar{a})^2
(ai−aˉ)2 进行排序,跑最小生成树就可以了,边跑边记录加入了哪些边及总边权和,跑完后算出正确的平均数,更新答案。
平均数每次加
0.25
0.25
0.25. (不明原因)
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#define ll long long
#define ldb long double
using namespace std;
int n,m,cnt,fa[110];
ldb maxn,ans,lyx,b[110];
struct c {
int x,y;
ldb w,v;
} a[2010];
bool cmp(c l,c r) {
return l.v<r.v;
}
int find(int x) {
if(fa[x]==x)return fa[x];
else return fa[x]=find(fa[x]);
}
void kruskal() {
lyx=0,cnt=0;
sort(a+1,a+m+1,cmp);
for(int i=1; i<=n; i++)
fa[i]=i;
for(int i=1; i<=m; i++) {
int x=find(a[i].x),y=find(a[i].y);
if(x!=y) {
fa[x]=y;
lyx+=a[i].w;
b[++cnt]=a[i].w;
}
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d%Lf",&a[i].x,&a[i].y,&a[i].w);
a[i].v=a[i].w;
}
ans=2147483600;
for(ldb i=0.25; i<=100; i+=0.25) {
for(int j=1; j<=m; j++)
a[j].v=(a[j].w-i)*(a[j].w-i);
kruskal();
ldb x=lyx*1.0/(n-1)*1.0;
ldb kj=0;
for(int j=1; j<=cnt; j++)
kj=kj+(b[j]-x)*(b[j]-x);
ans=min(ans,kj);
}
printf("%.4Lf",sqrt(ans/(n-1)*1.0));
}