BZOJ 3754 Tree之最小方差树

Posted on 2016-08-20 10:21  ziliuziliu  阅读(225)  评论(0编辑  收藏  举报

枚举平均数。

mdzz编译器。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxv 100500
#define maxe 200500
using namespace std;
int n,m,l=0,r=0,father[maxv],rank[maxv];
double ans=999999999999999999999999999999.0;
struct edge
{
    int u,v,w;
    double val;
}e[maxe];
bool cmp1(edge x,edge y)
{
    return x.w<y.w;
}
bool operator < (const edge &a,const edge &b){return a.val<b.val;}
int getfather(int x)
{
    if (father[x]!=x)
        father[x]=getfather(father[x]);
    return father[x];
}
void unionn(const int u,const int v)
{
    if(rank[u]<rank[v]) father[u]=v;
    else
    {
        father[v]=u;
        if(rank[u]==rank[v]) ++rank[u];
    }
}
double sqr(const double &x){return x*x;}
void kruskal(const int &x)
{
    int sum1=0,cnt=0;
    double sum2=0,ww=(double)x/(double)(n-1);
    for (int i=1;i<=n;i++) father[i]=i;
    memset(rank,0,sizeof(rank));
    for (int i=1;i<=m;i++)
        e[i].val=sqr(e[i].w-ww);
    sort(e+1,e+m+1);
    for(int i=1;i<=m;i++)
    {
        int f1=getfather(e[i].u),f2=getfather(e[i].v);
        if(f1!=f2)
        {
            unionn(f1,f2);
            sum1+=e[i].w;
            sum2+=e[i].val;
            if((++cnt)==n-1) break;
        }
    }
    if (sum1==x)
        ans=min(ans,sum2);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    sort(e+1,e+m+1,cmp1);   
    for (int i=1;i<=n-1;i++) l+=e[i].w;
    for (int i=m-n+2;i<=m;i++) r+=e[i].w;
    for (int i=l;i<=r;i++)
        kruskal(i);
    printf("%.4f\n",sqrt(ans/(double)(n-1)));
    return 0;
}