CF101D Castle 树形DP、贪心
题意:给出一个有$N$个点的树,你最开始在$1$号点,经过第$i$条边需要花费$w_i$的时间。每条边只能被经过$2$次。求出到达除$1$号点外所有点的最早时间的最小平均值。$N \leq 10^5 , w \leq 1000$
设$f_i$表示以第$i$个点为子树的最小总时间,考虑由儿子向父亲合并,额外定义$dis_i$为$i$到其父亲的边的边权,$t_i$表示从$t$的父亲走完根节点为$t$的子树再回到$t$的时间,也就等于$(\text{子树边权和+与父亲相连的边的边权})\times 2$,再定义$size_i$表示以$i$为根节点的子树的点数。可以$t_i$与$size_i$都是很容易从儿子向父亲合并的。
设我们正在算点$x$的答案,其儿子为$y_1,y_2...y_k$,且它们的答案已经算出来了。那么它的父亲的答案也就是$\sum\limits_{i=1}^k (f_{y_i}+dis_i \times size_i) + \sum\limits_{i=1}^k t_{p_i} \times (size_x - 1 - \sum\limits_{j=1}^i size_{p_i})$,其中$p_1,p_2...p_k$是一个$y_1,y_2...y_k$的排列,因为子树的选择是无序的,而在选择某个子树的时候,剩下没有选的所有点都需要等待这棵子树遍历完。
那么现在我们的任务转变为了找到一个最优的$p_1,p_2...p_k$的选择。考虑这个排列可能与排序有关,所以我们使用邻项交换的方法分析是否具有贪心策略。考虑相邻两个元素$p_i,p_i+1$,因为交换对于其他元素的答案是没有影响的,所以我们只需要考虑$p_i$与$p_{i+1}$的差别,将其他的设为$W$。
当我们的顺序是$p_i,p_{i+1}$时,答案是$f_{p_i}+t_{p_i} \times size_{p_{i+1}}+f_{p_{i+1}}+W$,而当顺序为$p_{i+1},p_i$时答案为$f_{p_{i+1}}+t_{p_{i+1}} \times size_{p_i}+f_{p_i}+W$。我们令第一种方案优于第二种方案,所以$f_{p_i}+t_{p_i} \times size_{p_{i+1}}+f_{p_{i+1}}+W < f_{p_{i+1}}+t_{p_{i+1}} \times size_{p_i}+f_{p_i}+W$,可以得到$t_{p_i} \times size_{p_{i+1}} < t_{p_{i+1}} \times size_{p_i}$。所以我们使用这个公式进行排序,就可以得到最优的方案。
#include<bits/stdc++.h>
#define ld long double
#define MAXN 500010
#define int long long
using namespace std;
inline int read(){
;
;
char c = getchar();
while(!isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(isdigit(c)){
a = (a << ) + (a << ) + (c ^ ');
c = getchar();
}
return f ? -a : a;
}
struct Edge{
int end , upEd , w;
}Ed[MAXN];
int head[MAXN] , siz[MAXN] , T[MAXN] , N , cntEd , forC;
ld dp[MAXN];
bool cmp(int a , int b){
return T[a] * siz[b] < T[b] * siz[a];
}
inline void addEd(int a , int b , int c){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
Ed[cntEd].w = c;
head[a] = cntEd;
}
void dfs(int now){
siz[now] = ;
vector < int > v;
for(int i = head[now] ; i ; i = Ed[i].upEd)
if(!siz[Ed[i].end]){
dfs(Ed[i].end);
siz[now] += siz[Ed[i].end];
T[Ed[i].end] += Ed[i].w << ;
dp[Ed[i].end] += Ed[i].w * siz[Ed[i].end];
v.push_back(Ed[i].end);
}
sort(v.begin() , v.end() , cmp);
; i < v.size() ; i++){
dp[now] += T[now] * siz[v[i]] + dp[v[i]];
T[now] += T[v[i]];
}
}
main(){
N = read();
; i < N ; i++){
int a = read() , b = read() , c = read();
addEd(a , b , c);
addEd(b , a , c);
}
dfs();
cout << ) << dp[] * );
;
}
CF101D Castle 树形DP、贪心的更多相关文章
- 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心
题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...
- [BZOJ1596] [Usaco2008 Jan]电话网络(树形DP || 贪心)
传送门 1.树形DP #include <cstdio> #include <cstring> #include <iostream> #define N 1000 ...
- bzoj 3829: [Poi2014]FarmCraft 树形dp+贪心
题意: $mhy$ 住在一棵有 $n$ 个点的树的 $1$ 号结点上,每个结点上都有一个妹子. $mhy$ 从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装 $zhx$ 牌杀毒 ...
- 树形DP+贪心(乱搞)(HDU4714)
题意:给出一个树形图,要求把该树形成一个环最少的步骤(断开一条边和形成一条边都需一步) 分析:很明显,要想把树形成一个环,就要先把其分裂成m条子链之后把子链形成环需要的步骤是2*m+1,所以只需要m最 ...
- [HNOI2003]消防局的设立 树形dp // 贪心
https://www.luogu.org/problemnew/show/P2279 一开始就想到了贪心的方法,不过一直觉得不能证明. 贪心的考虑是在深度从深到浅遍历每个结点的过程中,对于每个没有覆 ...
- POJ - 2057 The Lost House(树形DP+贪心)
https://vjudge.net/problem/POJ-2057 题意 有一只蜗牛爬上某个树枝末睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面,.现在这只蜗牛要求寻找 ...
- [POI2014]FAR-FarmCraft 树形DP + 贪心思想
(感觉洛谷上题面那一小段中文根本看不懂啊,好多条件都没讲,直接就是安装也要一个时间啊,,,明明不止啊!还好有百度翻译......) 题意:一棵树,一开始在1号节点(root),边权都为1,每个点有点权 ...
- ACM学习历程—FZU2195 检查站点(树形DP || 贪心)
Description 在山上一共有N个站点需要检查,检查员从山顶出发去各个站点进行检查,各个站点间有且仅有一条通路,检查员下山前往站点时比较轻松,而上山时却需要额外的时间,问最后检查员检查完所有站点 ...
- BZOJ4027/LG4107 「HEOI2015」兔子与樱花 树形DP+贪心
问题描述 LG4107 题解 首先,我们可以直接令结点 \(x\) 的权值为 \(c[x]+son_x\) ,发现将 \(x,y\) 合并,相当于增加 \(c[x]+c[y]-1\) 的重量. 容易想 ...
随机推荐
- Ubuntu 18 + Redis安装
Ubuntu 18 + Redis安装 1.安装命令: opengis@gisserver20:~$ sudo apt-get install redis-server 2.查看tcp 连接 open ...
- 在Visualforce页面中使用Visual Flow
在本文中,我们将通过一个示例说明如何将"流"(Visual Flow)用于Visualforce页面. 更全面的知识可以参考官方文档. 创建流 我们要创建一个流,它的作用是得到一个 ...
- 交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别
交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别 自己之前一直没搞清楚这两个交叉编译器到底有什么问题,特意google一番,总结如下,希望能帮到道上和 ...
- loadrunner 脚本开发-int型变量和字符串的相互转换
脚本开发-int型变量和字符串的相互转换 by:授客 QQ:1033553122 字符串转化为int型变量 Action2() { int j = 0; j = atoi("12345&qu ...
- SQLserver 还原数据库报“指定转换无效”的错的解决方案
最近在附加一个数据库的时候遇到一个问题:“指定转换无效”,经过分析,出现这个问题的原因可能是:1.版本不对.2.文件加密.3.文件损坏 解决方法: 一.版本不对: 1. 首先确定源数据库版本,下面 ...
- fedora 28 重新生成 /boot/grub2/grub.cfg
使用情景: 之前电脑安装了windows 7/ fedora 28 双系统,由于特殊原因,需要删除 windows 系统.在格式化硬盘后,我们还需要跟新 grub2 的启动条目:删除grub 启动的界 ...
- pyenv离线安装python各版本
1.问题描述: 可能是国内的网络原因,在线用pyenv安装python老是定住没反应 [root@zabbix ~]# pyenv install Downloading Python-.tar.xz ...
- iris数据集(.csv .txt)免费下载
我看CSDN下载的iris数据集都需要币,我愿意免费共享,希望下载后的朋友们给我留个言 分享iris数据集(供学习使用): 链接: https://pan.baidu.com/s/1Knsp7zn-C ...
- MATLAB常微分方程的数值解法
MATLAB常微分方程的数值解法 作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ 一.实验目的 科学技术中常常要求解常微分方程的定解问题,所谓数值解法就是 ...
- P1056 排座椅
非原创 #include<bits/stdc++.h>using namespace std;int t1[2009];int t2[2009]; int findmax(int *a){ ...