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

  

posted @ 2019-12-23 16:28  EM-LGH  阅读(149)  评论(0编辑  收藏  举报