• noip.ac 3286


    给定带权无向图,求出一颗方差最小的生成树。

    _________________________________________________

    方差就是各个数的平均值与各个数的差的平方的和的平均值。

    sum((a_i-ave)^2)/n

    多组数据。

    枚举是不现实的。但是不枚举如何知道他们的平均值?

    把所有的边排序,取出最小的n-1条和最大的n-1条分别求和,为mn和mx。那么ave*(n-1)一定在这个范围内。

    枚举这个值(也就是n-1条边的和),除以n-1就得到了平均值,用图中所有的变用这个平均值求差值的平方作为变得新权ww。用ww求新的最小生成树。

    开始,怀疑过:有些和是不会产生的,那么他们产生的方差会不会影响最终结果。

    假设,和为s时产生了平均数ave,用它选了相应最小的n-1条树边并产生的对应的方差。但是,这个和s并不会产生,当然ave也就不会产生。

    我们假设,对应的n-1条边真正产生的平均值是AVE,那么很明显AVE要比ave也好,当枚举到对应的值时自然会得到更好的解!

    _________________________________________________

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=55;
     4 const int maxm=1010;
     5 struct edge
     6 {
     7     int u,v;
     8     double w,ww;
     9 }e[maxm];
    10 int n,m,mn,mx;
    11 bool cmp(edge a,edge b)
    12 {
    13     return a.w<b.w;
    14 }
    15 bool cmp2(edge a,edge b)
    16 {
    17     return a.ww<b.ww;
    18 }
    19 double ans;
    20 int cas;
    21 int f[maxn];
    22 int find(int x)
    23 {
    24     return f[x]==x?x:f[x]=find(f[x]);
    25 }
    26 void join(int x,int y)
    27 {
    28     x=find(x);y=find(y);
    29     if(rand()%2)f[x]=y;
    30     else f[y]=x;
    31 }
    32 int main()
    33 {
    34     while(scanf("%d%d",&n,&m)==2 && n &&m)
    35     {
    36         cas++;
    37         for(int i=1;i<=m;++i)scanf("%d%d%lf",&e[i].u,&e[i].v,&e[i].w);
    38         sort(e+1,e+1+m,cmp);
    39         mn=mx=0;
    40         ans=100000000000;
    41         for(int i=1;i<n;++i)mn+=e[i].w;
    42         for(int i=m;i>m-n+1;--i)mx+=e[i].w;
    43         for(int i=mn;i<=mx;++i)
    44         {
    45             double tp=0;
    46             double pj=1.0*i/(n-1);
    47             for(int j=1;j<=m;++j)e[j].ww=(e[j].w-pj)*(e[j].w-pj);
    48             for(int j=1;j<=n;++j)f[j]=j;
    49             sort(e+1,e+1+m,cmp2);
    50             int js=0;
    51             for(int j=1;j<=m;++j)
    52             {
    53                 if(find(e[j].u)!=find(e[j].v))
    54                 {
    55                     join(e[j].u,e[j].v);
    56                     js++;
    57                     tp+=e[j].ww;
    58                     if(js==n-1)break;
    59                 }
    60             }
    61             ans=min(ans,tp);
    62         }
    63         printf("Case %d: %.2lf
    ",cas,ans/(n-1));
    64     }
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    百度首页暗藏的2019招聘广告彩蛋,非技术人员很难发现,看来是定向发送啊
    ipv6地址在URL中的表达方式,如何在URL地址中包含ipv6地址
    只用ipv6 两台机器共享文件夹, 局域网连接路径,共享文件夹路径中ipv6地址如何表示
    iconfont图标symbol引用方式,有的图标不能通过设置color样式来修改颜色的解决办法
    shell脚本面试题
    常用的Shell脚本
    JAVA面试题
    Linux系统基础优化
    Linux磁盘设备基础
    Linux系统的目录结构及常见目录总结
  • 原文地址:https://www.cnblogs.com/gryzy/p/14514027.html
Copyright © 2020-2023  润新知