2019 Multi-University Training Contest 8 - 1006 - Acesrc and Travel - 树形dp
http://acm.hdu.edu.cn/showproblem.php?pid=6662
仿照 CC B - TREE 那道题的思路写的,差不多。也是要走路径。
像这两种必须走到叶子的路径感觉是必须从INF出发,使得它强制从子树转移过来。否则假如可以在中间节点中断的话,初始值就是0,转移的时候假如子树更不好就不会更新这个0。
与哪个求每个点去往的最远点的标号(同样远的求最小标号)类似。
f[u]表示从u节点向下走向子树的最优值,这样必须dfs到叶子然后初始化叶子再返回。
g[u]表示从u节点向上走到父亲p,然后从父亲p绕另一条路(要么是走到祖父,要么是走到兄弟,所以f[p]要记录次优值以及最优值走向哪个儿子)的最优值,dfs的时候初始化根为它本身。
这样子定义导致在统计答案的时候要特判。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
ll val[MAXN];
vector<int> E[MAXN];
int ROOT;
void dfs1(int u, int p) {
if(E[u].size() == 1) {
ROOT = u;
return;
}
for(auto v : E[u]) {
if(v == p)
continue;
dfs1(v, u);
if(ROOT != -1)
return;
}
}
const ll INF = 1e18 + 1e17;
const ll INF2 = 1e16;
struct F {
ll val;
int son;
} fm1[MAXN], fm2[MAXN], fM1[MAXN], fM2[MAXN], tmpm, tmpM;
inline void InitF(int n) {
for(int i = 1; i <= n; ++i) {
fm1[i].val = fm2[i].val = INF;
fM1[i].val = fM2[i].val = -INF;
fm1[i].son = fm2[i].son = fM1[i].son = fM2[i].son = -1;
}
}
void maintainF(int u, int v) {
if(tmpM.val < fm2[u].val) {
fm2[u] = tmpM;
fm2[u].son = v;
if(fm2[u].val < fm1[u].val) {
swap(fm1[u], fm2[u]);
}
}
if(tmpm.val > fM2[u].val) {
fM2[u] = tmpm;
fM2[u].son = v;
if(fM2[u].val > fM1[u].val) {
swap(fM1[u], fM2[u]);
}
}
}
void dfsF(int u, int p) {
if(E[u].size() == 1 && E[u][0] == p) {
fm1[u].val = val[u];
fM1[u].val = val[u];
fm1[u].son = u;
fM1[u].son = u;
return;
}
for(auto v : E[u]) {
if(v == p)
continue;
dfsF(v, u);
tmpM = fM1[v];
tmpm = fm1[v];
maintainF(u, v);
}
fm1[u].val += val[u];
fm2[u].val += val[u];
fM1[u].val += val[u];
fM2[u].val += val[u];
}
struct G {
ll val;
} gm[MAXN], gM[MAXN];
inline void InitG(int n) {
for(int i = 1; i <= n; ++i) {
gm[i].val = INF;
gM[i].val = -INF;
}
}
F getFm(int u, int p) {
if(fm1[p].son == u)
return fm2[p];
return fm1[p];
}
F getFM(int u, int p) {
if(fM1[p].son == u)
return fM2[p];
return fM1[p];
}
void maintainG(int u, int p) {
if(p == -1) {
gm[u].val = val[u];
gM[u].val = val[u];
return;
}
gm[u].val = max(getFM(u, p).val, gM[p].val) + val[u];
gM[u].val = min(getFm(u, p).val, gm[p].val) + val[u];
}
void dfsG(int u, int p) {
maintainG(u, p);
for(auto v : E[u]) {
if(v == p)
continue;
dfsG(v, u);
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld", &val[i]);
for(int i = 1, b; i <= n; ++i) {
scanf("%d", &b);
val[i] -= b;
}
for(int i = 1; i <= n; ++i)
E[i].clear();
for(int i = 1; i <= n - 1; ++i) {
int u, v;
scanf("%d%d", &u, &v);
E[u].push_back(v);
E[v].push_back(u);
}
ROOT = -1;
dfs1(1, -1);
//ROOT是其中一个叶子
InitF(n);
dfsF(ROOT, -1);
InitG(n);
dfsG(ROOT, -1);
ll ans = -INF;
for(int i = 1; i <= n; ++i) {
ll tmp = (E[i].size() == 1 && i != ROOT ? INF : fm1[i].val);
tmp = min(tmp, (i != ROOT) ? (gm[i].val) : INF);
ans = max(ans, tmp);
}
printf("%lld\n", ans);
}
return 0;
}
假如定义f和g不包含节点本身的话,那是不是不需要特判呢?只能说是判得更恶心了。
2019 Multi-University Training Contest 8 - 1006 - Acesrc and Travel - 树形dp的更多相关文章
- 吉首大学2019年程序设计竞赛(重现赛)-J(树形DP)
题目链接:https://ac.nowcoder.com/acm/contest/992/J 题意:题意很清晰,就是求任意两点距离的和,结果对1e9+7取模. 思路:裸的树形DP题,一条边的贡献值=这 ...
- 2019 Multi-University Training Contest 7 - 1006 - Snowy Smile - 线段树
http://acm.hdu.edu.cn/showproblem.php?pid=6638 偷学一波潘哥的二维离散化和线段树维护最大子段和. 思路是枚举上下边界,但是不需要从左到右用最大子段和dp. ...
- 2019 Multi-University Training Contest 3 - 1006 - Fansblog - 打表 - 暴力
http://acm.hdu.edu.cn/showproblem.php?pid=6608 题意:给一个比较大的质数P(1e14以内),求比它小的最大的质数Q(貌似保证存在的样子,反正我没判不存在) ...
- 2015 Multi-University Training Contest 2 1006 Friends
Friends Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5305 Mean: n个人,m对朋友关系,每个人的朋友中又分为在线 ...
- 2015 Multi-University Training Contest 3 1006 Beautiful Set
Beautiful Set Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5321 Mean: 给出一个集合,有两种计算集合的值的 ...
- HDU 6324.Problem F. Grab The Tree-博弈(思维) (2018 Multi-University Training Contest 3 1006)
6324.Problem F. Grab The Tree 题目看着好难,但是题解说的很简单,写出来也很简单.能想出来就是简单的,想不出来就难(讲道理,就算是1+1的题目,看不出来就是难的啊). 和后 ...
- 2015 Multi-University Training Contest 2 1006 Friends 壮压
题目链接 题意:t 组測试数据,每组測试数据有 n个人,m条关系 每条关系能够是 "线上关系" 或者 "线下关系". 要求每一个人的线上关系(条数) == 线下 ...
- 2019 Nowcoder Multi-University Training Contest 4 E Explorer
线段树分治. 把size看成时间,相当于时间 $l$ 加入这条边,时间 $r+1$ 删除这条边. 注意把左右端点的关系. #include <bits/stdc++.h> ; int X[ ...
- 2019 Nowcoder Multi-University Training Contest 1 H-XOR
由于每个元素贡献是线性的,那么等价于求每个元素出现在多少个异或和为$0$的子集内.因为是任意元素可以去异或,那么自然想到线性基.先对整个集合A求一遍线性基,设为$R$,假设$R$中元素个数为$r$,那 ...
随机推荐
- 上一个树形菜单的改进,增添了数据绑定功能而非仅仅的jq特效
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- 上传本地文件到linux
Linux 命令行上传文件 Linux服务器,硬盘坏了,更换硬盘后,重装了好像是Foreda v22的操作系统,我在/var/www/html/目录下新建了我的个人文件夹 kma,然后我在此kma文件 ...
- 20175215 2018-2019-2 第四周Java课程学习总结
第五章学习内容 1.子类的继承性 (1)子类和父类在同一包中的继承性 如果子类和父类在同一个包中,那么,子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,并且也自然地继承了父类中 ...
- 【python学习】字符串相关
# -*- coding: utf-8 -*- # ========================================================================== ...
- RF变量
变量作用域 变量类型 变量作用域 case中的变量 case内部 userkeyword中的变量 userkeyword内部 文件型suite里的变量 文件suite内部,其下case均可使用 目录型 ...
- [转]maven中scope详解
在POM 4中,<dependency>中还引入了<scope>,它主要管理依赖的部署.目前<scope>可以使用5个值: * compile,缺省值,适用于所有阶 ...
- Linux 查找当前目录下 包含特定字符串 的所有文件
使用 Linux 经常会遇到这种情况:只知道文件中包含某些特定的字符串,但是不知道具体的文件名.需要根据“特定的字符串”反向查找文件. 示例(路径文件如下): ./miracle/luna/a.txt ...
- MySQL 树形结构 根据指定节点 获取其所有父节点序列
背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所有父节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取父节点. 2.直接自定义MySQL函数 ...
- Python实现利用最大公约数求三个正整数的最小公倍数示例
Python实现利用最大公约数求三个正整数的最小公倍数示例 本文实例讲述了Python实现利用最大公约数求三个正整数的最小公倍数.分享给大家供大家参考,具体如下: 在求解两个数的小公倍数的方法时,假设 ...
- oracle的表分析
对一个schema下所有对象的进行统计分析 dbms_stats.gather_schema_stats(ownname=> 'trade',estimate_percent => dbm ...