# bzoj3754: Tree之最小方差树

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int maxn=505,maxm=10010;
using namespace std;
struct Edge{int x,y,v;double w;}E[maxm];
int n,m,fa[maxn],cnt;double ans=1e9,w[2000010];bool in[maxm];
bool cmp1(Edge a,Edge b){return a.v<b.v;}
bool cmp2(Edge a,Edge b){return a.w<b.w;}
int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
double sqr(double x){return x*x;}
double kruskal(double mid){
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++) E[i].w=sqr(E[i].v-mid),in[i]=0;
sort(E+1,E+1+m,cmp2);int num=0;double len=0.0;
for (int i=1;i<=m&&num<n-1;i++){
int x=E[i].x,y=E[i].y;
if (getfa(x)==getfa(y)) continue;
num++,fa[getfa(x)]=getfa(y),len+=E[i].v,in[i]=1;
}
double res=0.0,aver=len/(n-1);
for (int i=1;i<=m;i++) if (in[i]) res+=sqr(E[i].v-aver);
return sqrt(res/(n-1));
}

int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].v);
sort(E+1,E+1+m,cmp1);
for (int i=1;i<=m;i++)
for (int j=i;j<=m;j++)
w[++cnt]=(E[i].v+E[j].v)/2.0;
sort(w+1,w+1+cnt),cnt=unique(w+1,w+1+cnt)-w-1;
ans=min(ans,kruskal(w[1]/2.0)),ans=min(ans,kruskal(w[cnt]+1.0));
for (int i=1;i<cnt;i++) ans=min(ans,kruskal((w[i]+w[i+1])/2.0));
printf("%.4lf\n",ans);
return 0;
}

/*
3 3
1 2 1
2 3 2
3 1 3
*/

posted @ 2016-01-14 09:39  orzpps  阅读(356)  评论(0编辑  收藏  举报