【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< ...
随机推荐
- See You Again——我最后的汇编程序
汇编语言:课程设计2 前言 由于本人水平不够,这里的课程设计2的程序实现并没有像王爽书中所说的那样可以不依赖于操作系统运行. 这里的程序依然要在dos下运行,而且没有实现引导现有操作系统的功能. 该程 ...
- C#实现窗口最小化到系统托盘
先添加notifyicon控件notifyIcon1 using System; using System.Collections.Generic; using System.ComponentMod ...
- 杭州优步uber司机第三组奖励政策
-8月9日更新- 优步杭州第三组: 定义为激活时间在2015/8/3之后(含)的车主(以优步后台数据显示为准) 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册Ub ...
- SQL 从入门到 DBA 删库跑路
SQL 从入门到 DBA 删库跑路 一.基础 人员信息表: ID 姓名 性别 出生 婚否 学历 工资 工会 35009449 孙xx 男 1978-2-17 未婚 中专 3000 TRUE 35000 ...
- Objective-C Block数据类型 @protocol关键字
Block数据类型 Block封装了一段代码 可以在任何时候执行 Block可以作为函数参数或者函数的返回值 而其本身又可以带输入参数或返回值 苹果官方建议尽量多用Block 在多线程 异步任务 集合 ...
- CSS 之 选择器
CSS的常见选择器 一.简单选择器 Simple Selectors 选择器 含义 * 通用元素选择器,匹配任何元素 E 标签选择器,匹配所有使用E标签的元素 .info class选择器,匹配所有c ...
- 使用Docker部署java web项目
在国内可能会有源下载失败问题,docker安装失败, 这里提供docker离线安装包如有需要可以进行下载 docker离线安装包下载 ##本文环境使用centos 7 进行部署. #1安装docker ...
- 【Linux】Face Recognition的封装
使用虹软的人脸识别 写了一个linux下的Face Recognition的封装,当作是练习. C++的封装,结合opencv,使用方便.https://github.com/zacario-li/F ...
- oracle数据库分页原理
Oracle数据库的rownum 在Oracle数据库中,分页方式没有MySql这样简单,它需要依靠rownum来实现.Rownum表示一条记录的行号,值得注意的是它在获取每一行后才赋予.因此,想指定 ...
- NFC进场通信总结概述
简介 本文介绍Nokia设备所支持的近场通信技术(NFC)及相关的功能.旨在为使用 Qt/Symbian/Java™ API为Nokia手机开发应用的开发者 刚开始接触NFC开发时提供有用的信息. 什 ...