题目大意:有一棵苹果树,每个节点有一个苹果,吃掉 uuu 点的苹果能获得 aua_uau​点 HP,经过第 iii 条边需要消耗 wiw_iwi​ HP,在原地等待一秒可以获得 111 HP,每条边只能经过两次,问从1号节点出发吃掉所有苹果最少需要等待多少秒。

分析:首先在某个点一次性把所需要的HP等够是显然正确的,根据每条边只能经过两次,解的形式一定是先吃掉某棵子树,再回到根,再吃其它子树,最优解是一个吃的顺序的问题,而吃掉子树是一个子问题,考虑用树形 dp。

设 dp[u]dp[u]dp[u] 表示以 uuu 为根的答案, sum[u]sum[u]sum[u] 表示吃完 uuu 的子树后 HP 的变化。

sum[u]sum[u]sum[u] 转移方程:sum[u]=∑v∈son(u)(sum[v]−2∗wv)sum[u] = \sum_{v\in son(u)}(sum[v] - 2 * w_v)sum[u]=∑v∈son(u)​(sum[v]−2∗wv​)
dp[u]dp[u]dp[u] 的转移要考虑子树的遍历顺序。

对于第 iii 棵子树,进入到这棵子树需要 ai=dp[i]+wia_i = dp[i] + w_iai​=dp[i]+wi​,从他回到 uuu 后 得到的 HP 为 bi=dp[i]+sum[i]−wib_i=dp[i]+sum[i]-w_ibi​=dp[i]+sum[i]−wi​

对遍历顺序进行分类讨论,简化问题,考虑只有两棵子树时的遍历顺序:

先遍历 bi≥aib_i \geq a_ibi​≥ai​ 的子树更优:

设有 ai≤bi,aj>bja_i \leq b_i,a_j > b_jai​≤bi​,aj​>bj​,分别讨论先 iii 和先 jjj 的答案:
1、若 ai≥aja_i \geq a_jai​≥aj​,则两种情况答案分别为:aia_iai​, aj+ai−bja_j + a_i - b_jaj​+ai​−bj​
2、若 ai<aja_i < a_jai​<aj​,则两种情况答案分别为:ai+max(aj−bi,0)a_i + max(a_j - b_i,0)ai​+max(aj​−bi​,0) , aj+max(ai−bj,0a_j + max(a_i - b_j,0aj​+max(ai​−bj​,0,画一下发现先 iii 答案至多为 aja_jaj​,而先 jjj 答案至少为 aja_jaj​

若均满足 a<ba<ba<b:
设有 ai≤bi,aj≤bja_i \leq b_i, a_j \leq b_jai​≤bi​,aj​≤bj​,设 ai<aja_i < a_jai​<aj​
两种情况答案分别为:ai+max(aj−bi,0)a_i + max(a_j - b_i,0)ai​+max(aj​−bi​,0),aja_jaj​,由于 bi≥aib_i \geq a_ibi​≥ai​,显然有 ai+max(aj−bi,0)≤aja_i + max(a_j - b_i,0) \leq a_jai​+max(aj​−bi​,0)≤aj​

若均满足 a>ba>ba>b:
设有 ai>bi,aj>bja_i > b_i, a_j > b_jai​>bi​,aj​>bj​
两种情况分别为:ai+max(aj−bi,0)a_i + max(a_j - b_i,0)ai​+max(aj​−bi​,0),aj+max(ai−bj,0)a_j + max(a_i - b_j,0)aj​+max(ai​−bj​,0),在纸上画一下可以发现先遍历 bbb 更大的子树更优。


代码:

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
typedef long long ll;
const int maxn = 1e5 + 10;
vector<pii> g[maxn];
int t, n, a[maxn];
ll dp[maxn], sum[maxn];
struct node {ll in, out;node() {}node(ll i,ll j) {in = i, out = j;}
};
bool cmp1(node x,node y) {return x.in < y.in;
}
bool cmp2(node x,node y) {return x.out > y.out;
}
void dfs(int u,int fa) {dp[u] = 0, sum[u] = a[u];vector<node> x, y;for (auto it : g[u]) {int v = it.fir, w = it.sec;if (v == fa) continue;dfs(v,u);sum[u] += sum[v] - 2ll * w;node t;if (w <= dp[v] + sum[v])t = node(w + dp[v],dp[v] + sum[v] - w);elset = node(2ll * w - sum[v],0);if (t.in <= t.out)x.push_back(t);elsey.push_back(t);}sort(x.begin(),x.end(),cmp1);sort(y.begin(),y.end(),cmp2);ll cur = a[u];for (auto it : x) {if (it.in > cur) {dp[u] += it.in - cur;cur = it.in;}cur = cur - it.in + it.out;}for (auto it : y) {if (it.in > cur) {dp[u] += it.in - cur;cur = it.in;}cur = cur - it.in + it.out;}
}
int main() {scanf("%d",&t);while (t--) {scanf("%d",&n);for (int i = 1; i <= n; i++)g[i].clear();for (int i = 1; i <= n; i++)scanf("%d",&a[i]);for (int i = 1; i < n; i++) {int u, v, w;scanf("%d%d%d",&u,&v,&w);g[u].push_back(pii(v,w));g[v].push_back(pii(u,w));}dfs(1,0);printf("%lld\n",dp[1]);}return 0;
}

2020牛客多校9:B. Groundhog and Apple Tree(树形DP + 分类讨论 + 贪心)相关推荐

  1. 2020 牛客多校第一场

    2020 牛客多校第一场 A. B-Suffix Array 后缀数组的思想:倍增+桶排序的方式找出一串连续序列后缀的大小.虽说正常使用的时候都是字典序,但是只要修改排序方式,也能够达到一个类似的&q ...

  2. 2020牛客多校 J Easy Integration 计算过程详解【点火公式(Wallis积分)+组合数学】

    2020牛客暑期多校训练营(第一场) J Easy Integration 题 网上题解大多是 不断分部积分求解,其实有更为简洁的解法. 便是 Wallis积分(点火公式) + 组合数学 求解,本文给 ...

  3. 【牛客 - 157D】插排树(dfs,树形dp)

    题干: 链接:https://ac.nowcoder.com/acm/contest/157/D 来源:牛客网 一年一度的山东省oi夏令营又开始了,每到这个季节,山东的oier们都会欢聚这里,一起学( ...

  4. [2020牛客多校第一场]Coda的题解集

    被暴打了. 会先写比赛中过题数100+的题目,其他的以后再补. 施工中,未完待续- F Infinite String Comparision 一开始想到的是对比到lcm(|a|,|b|),意料之中T ...

  5. 2020牛客多校联赛第四场 (BFH)

    文章目录 B:Basic Gcd Problem 题目 翻译 例子 大意 思路 代码 F:Finding the Order 题目 翻译 例子 大意 思路 代码 H:Harder Gcd Proble ...

  6. 2020牛客多校第1场H-Minimum-cost Flow

    解题思路: 首先我们要从费用流mcmf的算法入手:因为它每次增广是再费用增广路上跑的,根据贪心的思想费用小的路基本上能运多少就尽量运多少,所以我们可以假设初始的边容量是1,只跑一遍mcmf.记录一下每 ...

  7. 数论分块 ---- 2020牛客多校第7场H-Dividing[思维+数论分块]

    题目大意: 解题思路:很明显满足条件的点是n%k==0∣∣n%k==1n\%k==0||n\%k==1n%k==0∣∣n%k==1 1.因为nnn是从111开始的如果一直乘以k[n=n∗k]k[n=n ...

  8. 2020牛客多校第7场C-A National Pandemic[树链剖分+思维]

    题目大意 1.首先我们看一下操作1:实际上可以说成在所有位置上加上w−dist(x,y)w-dist(x,y)w−dist(x,y),因为dist(x,x)=0dist(x,x)=0dist(x,x) ...

  9. 2020牛客多校第一场B虚树+质数筛+换根dp

    题目大意: 1.可以发现阶乘增长是很快的所以你要把整颗树建立出来是不实际的. 2.我们可以假设这棵树已经建出来出来了我们应该怎么搞 首先很明显是一个树形dp, 我们设dp[j],是以j为u到其他点距离 ...

最新文章

  1. CSS中一些语法规范和代码风格
  2. Science 好文:强化学习之后,机器人学习瓶颈如何突破?
  3. KS008基于SSM的新闻发布系统
  4. Xcode12.5最新快捷键的使用(学会事半功倍)
  5. 敏捷 冲刺_在这个敏捷的假期季节给予技术债务冲刺的礼物
  6. linux 刻录cd,Linux 刻录CD/DVD命令 growisofs/mkisofs/cdrecord
  7. 推荐系统(2)-协同过滤1-UserCF、ItemCF
  8. TensorFlow 学习指南 四、分布式
  9. C#(asp.net)实现目录(无扩展名)重写
  10. 以京东为代表电商平台成中华老字号销售增速最快渠道
  11. 【Flutter】Dart中的Mixins混入你知道是什么吗?
  12. core部署iis的 调试net_ASP.NET Core环境变量和启动设置的配置教程
  13. 传输层的端口与TCP标志中的URG和PSH位
  14. 五大地形等高线特征_【新微专题】从等高线地形图的实际应用分析如何培养图表判读能力?...
  15. Wex5 app 学习笔记(二)
  16. DATABASE_ROUTERS在Django中使用多个MySQL数据库进行配置
  17. AFNetworkReachabilityManager检测网络状态
  18. excel2019如何做下拉菜单选项(数据源不占用原表上的单元格)
  19. c语言(http://c.biancheng.net/view/1714.html)
  20. 【Java专题】Java中的I/O流详解

热门文章

  1. 银行携手基金推类“余额宝”产品
  2. C++学习笔记_002_对象特性(续)
  3. 【过一下6】机器视觉视频 【过一下2被挤掉了】
  4. Leetcode周赛专题
  5. TZC 1283: 简单排序 —— 比较排序
  6. 夏季养生保健 10个常识女人夏季养生必备
  7. 十、矩阵零空间、线性无关、列空间、列空间的基、零度、秩等概念的整合
  8. linux网络协议栈招聘,Linux 网络协议栈开发(一)ping命令
  9. ad敷铜后还有部分飞线_AP刺客才是刺客之王!虎牙整活杯刺客大战,AD刺客遗憾落败...
  10. 【知识蒸馏】2021年最新知识蒸馏综述和论文总结