【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< ...
随机推荐
- python通过mongoengine中connect函数连接多个数据库
mongoengine支持程序同时连接多个数据库,这些数据库可以位于一个或多个mongo之中,通过alias名称区分不同的连接即可. 可以通过switch_db切换到不同的数据库,进行读写操作,swi ...
- you selected does not support x86-64 instruction set
centos 安装redis时报you selected does not support x86-64 instruction set 解决方法 make CFLAGS="-march=x ...
- 抽样分布(3) F分布
定义 设U~χ2(n1), V~χ2(n2),且U,V相互独立,则称随机变量 服从自由度为(n1,n2)的F分布,记为F~F(n1,n2),其中n1叫做第一自由度,n2叫做第二自由度. F分布的概率密 ...
- 一步一步学习JNI
本文来自网易云社区 作者:孙有军 前言 本篇的主要目的就是JNI开发入门,使大家对JNI开发流程有一个大致的了解,后续再进行深入学习. JNI不是Android特有的,JNI是Java Native ...
- create-react-app react-redux项目 配置模块热更新hmr
HRM并不是create-react-app专属的,提供一篇博客介绍hrm http://chrisshepherd.me/posts/adding-hot-module-reloading-to-c ...
- 180615-精度计算BigDecimal
文章链接:https://liuyueyi.github.io/hexblog/2018/06/15/180615-精度计算BigDecimal/ 180615-精度计算BigDecimal 目前接触 ...
- Web应用服务器性能压力测试
压力测试需要关注三个方面:如何正确产生压力.如何定位瓶颈.如何预估系统的承载能力 产生压力的方法 通常可以写脚本产生压力机器人对服务器进行发包和收包操作,也可以使用现有的工具(像jmeter.Load ...
- TW实习日记:第20-21天
为什么上周五没写呢,因为上周五一直在熟悉业务流程...根本不会写一些复杂的业务代码,因为没有业务流程图!!!在学校的上需求分析和UML建模课的时候,还有软件工程课的时候,想着这都什么鬼啊,听来干嘛,写 ...
- leetcode-岛屿的个数
岛屿的个数 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 ...
- Python基础 之 数据类型
数据类型 一.运算符 算数运算a = 10 * 10赋值运算a = a + 1 a+=1 布尔值:True 真 False 假 if True: pass while True: pass v = n ...