BZOJ 3754: Tree之最小方差树 枚举+kruskal
你发现平均值不会很大,所以直接暴力枚举平均值,然后跑 4*100 次最小生成树取最小值即可.
code:
#include <cstdio>
#include <cmath>
#include <algorithm>
#define N 2005
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,m;
int fa[N];
int ans=0x3f3f3f3f,sum1,sum2;
struct Edge
{
int u,v,w;
double fc;
friend bool operator<(Edge a,Edge b)
{
return a.fc<b.fc;
}
}edge[N];
int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); }
int main()
{
// setIO("input");
scanf("%d%d",&n,&m);
int i,j;
for(i=1;i<=m;++i) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
for(double av=0.0;av<=100;av+=0.25)
{
sum1=sum2=0;
for(i=1;i<=n;++i) fa[i]=i;
for(i=1;i<=m;++i) edge[i].fc=(edge[i].w-av)*(edge[i].w-av);
sort(edge+1,edge+1+m);
for(i=1;i<=m;++i)
{
int u=edge[i].u,v=edge[i].v;
int uu=find(u),vv=find(v);
if(uu!=vv)
{
sum1+=edge[i].w,sum2+=edge[i].w*edge[i].w;
fa[vv]=uu;
}
}
ans=min(ans,(n-1)*sum2-sum1*sum1);
}
printf("%.4lf\n",sqrt(ans)/(n-1));
return 0;
}

浙公网安备 33010602011771号