【bzoj3754】Tree之最小方差树 最小生成树
题目描述
输入
输出
样例输入
3 3
1 2 1
2 3 2
3 1 3
样例输出
0.5000
题解
最小生成树
由于Ci很小,因此选出边的总和不会很大。可以考虑枚举这个总和(即平均值)。
然后把每条边的边权看作 $|c_i-\bar c|$ ,跑最小生成树,记录选出的边,然后根据实际选择计算实际方差(注意这里算平均值用的不是枚举的总和,而是实际计算的平均值)
简单证明一下这样为什么是对的:当枚举的总和是最终答案的总和时,选出的边一定是最终答案,而每次计算的答案不会出现错误情况,因此它们的最小值一定是答案。
细节处理中,可以先对所有边按照权值排序,在枚举总和(平均值)时,记录第一个大于等于这个平均值的边的位置 $p$ 。这样,这个位置 $p$ 左边的代价就是 $\bar c-c_i$ ,右边的代价就是 $c_i-\bar c$ ,使用二路归并的方法依次取最小值即可。这个方法可以避免每次都对所有边排序。
时间复杂度 $O(m\log 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\n" , sqrt(ans / (n - 1)));
return 0;
}
【bzoj3754】Tree之最小方差树 最小生成树的更多相关文章
- bzoj3754 Tree之最小方差树 最小生成树+推性质
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3754 题解 感觉这个思路挺神仙的. 后悔没有好好观察题目的数据范围,一直把 \(n\) 和 \ ...
- [BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树
[BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树 题目大意: 给定一个\(n(n\le50)\)个点,\(m(m\le1000 ...
- [BZOJ3754]Tree之最小方差树
3754: Tree之最小方差树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 402 Solved: 152[Submit][Status][Di ...
- 【枚举】【最小生成树】【kruscal】bzoj3754 Tree之最小方差树
发现,若使方差最小,则使Σ(wi-平均数)2最小即可. 因为权值的范围很小,所以我们可以枚举这个平均数,每次把边权赋成(wi-平均数)2,做kruscal. 但是,我们怎么知道枚举出来的平均数是不是恰 ...
- bzoj 3754: Tree之最小方差树 模拟退火+随机三分
题目大意: 求最小方差生成树.N<=100,M<=2000,Ci<=100 题解: 首先我们知道这么一个东西: 一些数和另一个数的差的平方之和的最小值在这个数是这些数的平均值时取得 ...
- 【BZOJ 3754】: Tree之最小方差树
题目链接: TP 题解: 都是骗子233,我还以为是什么神奇的算法. 由于边权的范围很小,最小生成树和最大生成树之间的总和差不会太大,所以可以枚举边权和,再直接根据方差建最小生成树,每次更新答案即可. ...
- BZOJ 3754 Tree之最小方差树 MST
Description Wayne 在玩儿一个很有趣的游戏.在游戏中,Wayne 建造了N 个城市,现在他想在这些城市间修一些公路,当然并不是任意两个城市间都能修,为了道路系统的美观,一共只有M 对城 ...
- 【BZOJ 3754】Tree之最小方差树
http://www.lydsy.com/JudgeOnline/problem.php?id=3754 核心思想:暴力枚举所有可能的平均数,对每个平均数排序后Kruskal. 正确的答案一定是最小的 ...
- BZOJ 3754 Tree之最小方差树
枚举平均数. mdzz编译器. #include<iostream> #include<cstdio> #include<cstring> #include< ...
随机推荐
- 如何在两个jsp页面之间传值,在另外一个页面用EL表达式获取值
第一个jsp页面 <% String ids=request.getParameter("id"); int id=Integer.parseInt(ids); %> ...
- 环境变量Path简介
更多详细专业的详解,请参见:http://www.cnblogs.com/sunada2005/articles/2725277.html 什么是Path变量: PATH环境变量.作用是指定命令搜索路 ...
- 北京Uber优步司机奖励政策(1月27日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 北京Uber优步司机奖励政策(12月12日)
用户组:人民优步及电动车(适用于12月12日) 滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:htt ...
- 5 属性 property
1.属性 property 调用私有属性通过实例方法调用.达到这种效果 #property的作用:相当于把方法进行了封装, 开发者在对属性设置数据的时候更方便 class Dog(object): ...
- Emmet 技巧
1. Lorem 产生一段 dummy text 2. $ 变量的使用 3. 插入img的长度和宽度 使用快捷键ctrl+u插入图片的长度和宽度 注意光标要停留在图片文件名上. 其他在Sublime中 ...
- spark 相关
Spark为什么会比mapreduce快? 1.Spark减少了中间过程的磁盘读写,数据很多时候不需要落地,从而提升了效率. 2.Spark基于内存的读写,减少了磁盘IO.node数据交互的通信时间. ...
- docker社区的geodata/gdal镜像dockerfile分析
对应从事遥感与地理信息的同仁来说,gdal应该是所有工具中使用频度最高的库了,那么在docker中使用gdal时,面临的第一步就是构建gdal基础镜像,社区中引用最多的就是geodata提供的gdal ...
- MySQL☞upper函数
upper(列名/字符串):把小写字母改为大写字母 格式: select upper(列名/字符串) from 表名 如下图:
- docker官网安装
最近发现一些同学居然不会安装docker,难,不难,只是“网络不好”! 如果是学习的话,目前我发现的比较好的方法还是到清华的开源镜像网站: https://mirror.tuna.tsinghua.e ...