2018-team4-modules-最小方差生成树

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
//构成生成树的所有边的方差最小
#define EPS (1.0 / (n - 1))
struct Edge{
    int x,y,len;
    double temp;
    bool operator <(const Edge &a)const {return len < a.len;}
    void Read(){read(x);read(y);read(len);}
}G[maxn];
int n,m;
int fa[maxn];
int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
inline int MST(){
    for(int i = 1; i <= n; ++i) fa[i] = i;
    int re = 0;
    for(int i = 1; i <= m; ++i) {
        int fx = find(G[i].x);
        int fy = find(G[i].y);
        if(fx != fy) {
            fa[fx] = fy;
            re += G[i].len;
        }
    }
    return re;
}
inline bool cmp(const Edge &a,const Edge &b){return a.temp < b.temp;}
inline double Calc(double average){
    for(int i = 1; i <= n; ++i) fa[i] = i;
    for(int i = 1; i <= m; ++i)
        G[i].temp = (average - G[i].len) * (average - G[i].len);
    sort(G + 1,G + m + 1,cmp);
    double re = 0.0;
    for(int i = 1; i <= m; ++i) {
        int fx = find(G[i].x);
        int fy = find(G[i].y);
        if(fx != fy) {
            fa[fx] = fy;
            re += G[i].temp;
        }
    }
    return re / (n - 1);
}
int main(){
    read(n);read(m);
    for(int i = 1; i <= m; ++i) G[i].Read();
    sort(G + 1,G + m + 1);
    double range_min = (double)MST() / (n - 1);
    reverse(G + 1,G + m + 1);
    double range_max = (double)MST() / (n - 1);
    double ans = inf;
    for(int i = 0; EPS*i + range_min <= range_max; ++i)
        ans = min(ans,Calc(EPS*i + range_min));
    printf("%.4lf\n",ans);
    return 0;
}
}}}
//构成生成树的所有边的方差最小
#define EPS (1.0 / (n - 1))
struct Edge{
    int x,y,len;
    double temp;
    bool operator <(const Edge &a)const {return len < a.len;}
    void Read(){read(x);read(y);read(len);}
}G[maxn];
int n,m;
int fa[maxn];
int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
inline int MST(){
    for(int i = 1; i <= n; ++i) fa[i] = i;
    int re = 0;
    for(int i = 1; i <= m; ++i) {
        int fx = find(G[i].x);
        int fy = find(G[i].y);
        if(fx != fy) {
            fa[fx] = fy;
            re += G[i].len;
        }
    }
    return re;
}
inline bool cmp(const Edge &a,const Edge &b){return a.temp < b.temp;}
inline double Calc(double average){
    for(int i = 1; i <= n; ++i) fa[i] = i;
    for(int i = 1; i <= m; ++i)
        G[i].temp = (average - G[i].len) * (average - G[i].len);
    sort(G + 1,G + m + 1,cmp);
    double re = 0.0;
    for(int i = 1; i <= m; ++i) {
        int fx = find(G[i].x);
        int fy = find(G[i].y);
        if(fx != fy) {
            fa[fx] = fy;
            re += G[i].temp;
        }
    }
    return re / (n - 1);
}
int main(){
    read(n);read(m);
    for(int i = 1; i <= m; ++i) G[i].Read();
    sort(G + 1,G + m + 1);
    double range_min = (double)MST() / (n - 1);
    reverse(G + 1,G + m + 1);
    double range_max = (double)MST() / (n - 1);
    double ans = inf;
    for(int i = 0; EPS*i + range_min <= range_max; ++i)
        ans = min(ans,Calc(EPS*i + range_min));
    printf("%.4lf\n",ans);
    return 0;
}