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; }