• 【bzoj3754】Tree之最小方差树 最小生成树


    题目描述

    给出一张无向图,求它的一棵生成树,使得选出的所有边的方差最小。输出这个最小方差。

    输入

    第一行两个正整数N,M
    接下来M行,每行三个正整数Ui,Vi,Ci
    N<=100,M<=2000,Ci<=100

    输出

    输出最小的标准差,保留四位小数。

    样例输入

    3 3
    1 2 1
    2 3 2
    3 1 3

    样例输出

    0.5000


    题解

    最小生成树

    由于Ci很小,因此选出边的总和不会很大。可以考虑枚举这个总和(即平均值)。

    然后把每条边的边权看作 $|c_i-ar c|$ ,跑最小生成树,记录选出的边,然后根据实际选择计算实际方差(注意这里算平均值用的不是枚举的总和,而是实际计算的平均值)

    简单证明一下这样为什么是对的:当枚举的总和是最终答案的总和时,选出的边一定是最终答案,而每次计算的答案不会出现错误情况,因此它们的最小值一定是答案。

    细节处理中,可以先对所有边按照权值排序,在枚举总和(平均值)时,记录第一个大于等于这个平均值的边的位置 $p$ 。这样,这个位置 $p$ 左边的代价就是 $ar c-c_i$ ,右边的代价就是 $c_i-ar c$ ,使用二路归并的方法依次取最小值即可。这个方法可以避免每次都对所有边排序。

    时间复杂度 $O(mlog m+cnm)$

    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    struct data
    {
    	int x , y , z;
    	bool operator<(const data &a)const {return z < a.z;}
    }a[2010];
    bool v[2010];
    int f[110];
    int find(int x)
    {
    	return x == f[x] ? f[x] : f[x] = find(f[x]);
    }
    int main()
    {
    	int n , m , i , j , k , now , p = 1;
    	double s , t , ans = 1 << 30;
    	scanf("%d%d" , &n , &m);
    	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].z);
    	sort(a + 1 , a + m + 1);
    	for(i = 0 ; i <= (n - 1) * 100 ; i ++ )
    	{
    		while(p <= m && a[p].z * (n - 1) < i) p ++ ;
    		for(j = 1 ; j <= n ; j ++ ) f[j] = j;
    		for(j = 1 ; j <= m ; j ++ ) v[j] = 0;
    		j = p - 1 , k = p , s = t = 0;
    		while(j || k <= m)
    		{
    			if(k > m || (j && i - a[j].z * (n - 1) < a[k].z * (n - 1) - i)) now = j -- ;
    			else now = k ++ ;
    			if(find(a[now].x) != find(a[now].y))
    				f[f[a[now].x]] = f[a[now].y] , s += a[now].z , v[now] = 1;
    		}
    		s /= (n - 1);
    		for(j = 1 ; j <= m ; j ++ )
    			if(v[j])
    				t += (a[j].z - s) * (a[j].z - s);
    		ans = min(ans , t);
    	}
    	printf("%.4lf
    " , sqrt(ans / (n - 1)));
    	return 0;
    }
    
  • 相关阅读:
    寒假13
    寒假作业十二
    寒假12
    寒假作业十一
    寒假11
    寒假作业九
    寒假10
    寒假作业九
    寒假9
    寒假作业八
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8006209.html
Copyright © 2020-2023  润新知