zoukankan      html  css  js  c++  java
  • 【枚举】【最小生成树】【kruscal】bzoj3754 Tree之最小方差树

    发现,若使方差最小,则使Σ(wi-平均数)2最小即可。

    因为权值的范围很小,所以我们可以枚举这个平均数,每次把边权赋成(wi-平均数)2,做kruscal。

    但是,我们怎么知道枚举出来的平均数是不是恰好是我们的这n-1条边的呢? 就在更新答案的时候加个特判就行了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstring>
     5 using namespace std;
     6 #define N 101
     7 #define M 2001
     8 typedef double db;
     9 int fa[N],a[M],n,m,minv,maxv,rank[N];
    10 db ans=999999999999999999999999999999.0;
    11 bool cmp(const int &a,const int &b){return a>b;}
    12 struct Edge{int u,v,w;db fw;void Read(){scanf("%d%d%d",&u,&v,&w);}}edges[M];
    13 bool operator < (const Edge &a,const Edge &b){return a.fw<b.fw;}
    14 void init()
    15 {
    16     for(int i=1;i<=n;i++) fa[i]=i;
    17     memset(rank,0,sizeof(rank));
    18 }
    19 int findroot(int x)
    20 {
    21     if(x==fa[x]) return x;
    22     int rt=findroot(fa[x]);
    23     fa[x]=rt;
    24     return rt;
    25 }
    26 void Union(const int &U,const int &V)
    27 {
    28     if(rank[U]<rank[V]) fa[U]=V;
    29     else
    30       {
    31           fa[V]=U;
    32           if(rank[U]==rank[V]) ++rank[U];
    33       }
    34 }
    35 double sqr(const double &x){return x*x;}
    36 void kruscal(const int &sum)
    37 {
    38     init(); db BA=(db)sum/(db)(n-1);
    39     int tot=0,all=0; db f_all=0;
    40     for(int i=1;i<=m;++i) edges[i].fw=sqr((db)edges[i].w-BA);
    41     sort(edges+1,edges+m+1);
    42     for(int i=1;i<=m;++i)
    43       {
    44           int f1=findroot(edges[i].u),f2=findroot(edges[i].v);
    45           if(f1!=f2)
    46             {
    47                 Union(f1,f2);
    48                 all+=edges[i].w;
    49                 f_all+=edges[i].fw;
    50                 if((++tot)==n-1) break;
    51             }
    52       }
    53     if(all==sum) ans=min(ans,f_all);
    54 }
    55 int main()
    56 {
    57     scanf("%d%d",&n,&m);
    58     for(int i=1;i<=m;++i) {edges[i].Read(); a[i]=edges[i].w;}
    59     sort(a+1,a+m+1); for(int i=1;i<n;++i) minv+=a[i];
    60     sort(a+1,a+m+1,cmp); for(int i=1;i<n;++i) maxv+=a[i];
    61     for(int i=minv;i<=maxv;++i) kruscal(i);
    62     printf("%.4f
    ",sqrt(ans/(db)(n-1)));
    63     return 0;
    64 }
  • 相关阅读:
    用Creator实现一个擀面的效果
    游戏开发中的多语言处理
    Docker(六)容器数据卷
    Docker(五)Docker镜像讲解
    Docker(四)Docker镜像安装
    Docker(三)Docker常用命令
    Docker(二)Docker配置
    nginx 与 tomcat 组合搭建web服务
    Zookeeper 使用
    tomcat-manager 设置
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4120674.html
Copyright © 2011-2022 走看看