题目链接

传送门

题意

两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次经过,直到无法移动则结束游戏,两人都想最大化自己的权值和减对手权值和,问先手减后手权值和最大是多少。

思路

换根\(DP\),和求树的直径有点类似。

\(dp[i][j]\)表示在\(i\)这个结点状态为\(j\)时先手权值和减后手权值和最优是多少,\(j\)为偶数表示当前是先手,为奇数时为后手。

转移方程:我们该\(dp\)是倒着推的,也就是说从游戏结束开始往游戏开始推,假设当前是先手选择,那么下一步就是后手移动,按照题目要求后手一定是想最小化先手减后手权值和,因此当前一定是从最小的先手减后手权值和转移过来;如果当前是后手那么就从先手减后手权值和最大转移过来。

需要特别注意的两点是:

  • 从子结点转移过来很好想,就是子结点中相反状态转移过来,也就是当前为先手那么从最小过来;从父亲结点转移过来的时候,因为一个结点只有一个父亲结点,因此如果当前是先手,那么父亲结点也就确定了,因此它要从父亲结点从其他结点转移过来的最大值转移到当前结点,后手同理,枚举起点时由于你枚举之后起点也固定了,因此对于同一个起点要选择值最小的方向(因为这里我卡了好久,好菜啊)。

  • 最后枚举答案的时候如果当前点是叶子结点,那么它的答案是从父亲结点贡献的,不能由它自己贡献,因为如果先手选择这个点为起点,那么后手一定是往父亲结点选。

代码

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson (rt<<1),L,mid
#define rson (rt<<1|1),mid + 1,R
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 100000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int t, n, tot, x, u, v;
int a[maxn], head[maxn], du[maxn];
LL dp[maxn][6]; struct edge{
int v, next;
}ed[maxn*2]; void add(int u, int v) {
ed[tot].v = v;
ed[tot].next = head[u];
head[u] = tot++;
} void dfs1(int u, int p) {
for(int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if(v == p) continue;
dfs1(v, u);
++du[u];
if(dp[v][1] < dp[u][0]) {
dp[u][2] = dp[u][0];
dp[u][0] = dp[v][1];
} else {
dp[u][2] = min(dp[u][2], dp[v][1]);
}
if(dp[v][0] > dp[u][1]) {
dp[u][3] = dp[u][1];
dp[u][1] = dp[v][0];
} else {
dp[u][3] = max(dp[u][3], dp[v][0]);
}
}
if(dp[u][0] == INF) dp[u][0] = dp[u][1] = dp[u][2] = dp[u][3] = 0;
dp[u][0] += a[u], dp[u][2] += a[u];
dp[u][1] += a[u], dp[u][3] += a[u];
} void dfs2(int u, int p) {
for(int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if(v == p) continue;
if(du[u] == 1) {
dp[v][5] = dp[u][4] + a[v];
dp[v][4] = dp[u][5] + a[v];
} else {
if(dp[u][0] == dp[v][1] + a[u]) {
if(u != 1) dp[v][5] = min(dp[u][2], dp[u][4]) + a[v];
else dp[v][5] = dp[u][2] + a[v];
} else {
if(u != 1) dp[v][5] = min(dp[u][0], dp[u][4]) + a[v];
else dp[v][5] = dp[u][0] + a[v];
}
if(dp[u][1] == dp[v][0] + a[u]) {
if(u != 1) dp[v][4] = max(dp[u][3], dp[u][5]) + a[v];
else dp[v][4] = dp[u][3] + a[v];
} else {
if(u != 1) dp[v][4] = max(dp[u][1], dp[u][5]) + a[v];
else dp[v][4] = dp[u][1] + a[v];
}
}
dfs2(v, u);
}
} int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
tot = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
head[i] = -1;
du[i] = 0;
dp[i][0] = dp[i][2] = dp[i][4] = INF;
dp[i][1] = dp[i][3] = dp[i][5] = -INF;
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &x);
a[i] -= x;
}
for(int i = 1; i < n; ++i) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
dfs1(1, 0);
dp[1][4] = dp[1][5] = a[1];
dfs2(1, 0);
LL ans = dp[1][0];
for(int i = 2; i <= n; ++i) {
if(du[i] == 0) ans = max(ans, dp[i][4]);
else ans = max(ans, min(dp[i][4], dp[i][0]));
}
printf("%lld\n", ans);
}
return 0;
}

Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)的更多相关文章

  1. Make Rounddog Happy(2019年杭电多校第十场1011+HDU6701+启发式分治)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 求有多少个子区间满足\(a_l,a_{l+1},\dots,a_r\)均不相同且\(max(a_l,a_{l+1},\dots,a_r)-(r ...

  2. 2019年杭电多校第三场 1008题Game(HDU6610+带修改莫队+Nim博弈)

    题目链接 传送门 题意 给你\(n\)堆石子,每堆有\(a_i\)堆石子,\(q\)次操作: 在\([L,R]\)内有多少个子区间使得\(Alice\)(先手)在\(Nim\)博弈中获胜: 交换\(a ...

  3. 2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

    题目链接 传送门 题意 给你一棵无根树,要你寻找一个根节点使得在将一条边权变为\(0\)后,离树根最远的点到根节点的距离最小. 思路 本题和求树的直径很像,不过要记得的东西有点多,且状态也很多. \( ...

  4. 2019 杭电多校第八场 HDU - 6665 Calabash and Landlord 两矩形分平面

    题意 给出两个矩形,问这两个矩形把平面分成了几部分. 分析 不需要什么高级技能,只需 “简单” 的分类讨论. (实在太难写了,对拍找出错误都不想改 推荐博客,其中有个很好的思路,即只讨论答案为2,3, ...

  5. [2019杭电多校第八场][hdu6667]Roundgod and Milk Tea

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6667 题目大意是说n个班级,每个班级有ai人和bi杯茶,每个人只能喝其他班的茶并且只能喝一杯.问最多有 ...

  6. 杭电多校第八场-A-Character Encoding

    题目描述 In computer science, a character is a letter, a digit, a punctuation mark or some other similar ...

  7. 2018杭电多校第三场1003(状态压缩DP)

    #include<bits/stdc++.h>using namespace std;const int mod =1e9+7;int dp[1<<10];int cnt[1& ...

  8. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

  9. Rikka with Travels(2019年杭电多校第九场07题+HDU6686+树形dp)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 定义\(L(a,b)\)为结点\(a\)到结点\(b\)的路径上的结点数,问有种\(pair(L(a,b),L(c,d))\)取值,其中结点\ ...

随机推荐

  1. Linux性能优化实战学习笔记:第四十讲

    一.上节回顾 上一节,我们学习了碰到分布式拒绝服务(DDoS)的缓解方法.简单回顾一下,DDoS利用大量的伪造请求,导致目标服务要耗费大量资源,来处理这些无效请求,进而无法正常响应正常用户的请求. 由 ...

  2. [LeetCode] 882. Reachable Nodes In Subdivided Graph 细分图中的可到达结点

    Starting with an undirected graph (the "original graph") with nodes from 0 to N-1, subdivi ...

  3. [LeetCode] 159. Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串

    Given a string s , find the length of the longest substring t  that contains at most 2 distinct char ...

  4. Idea中自动生成get,set,toString等方法

    https://blog.csdn.net/sinat_41226396/article/details/80770520 自动生成main函数: https://blog.csdn.net/fanr ...

  5. plsql安装

    1.plsql都需要安装oracle的客户端,不过也可以安装瘦客户端,完整的客户端太大了,俗称胖客户端,一般瘦客户端就可以满足, 本人下载的是instantclient-basic-win32-11. ...

  6. [MSSQL]找出一天数据中从第一条数据开始每累加1小时的数据

    用Sql Server找出一天数据中从第一条数据开始每累加1小时的数据 -- ============================================= -- Author: Alle ...

  7. 【2019年07月22日】A股最便宜的股票

    查看更多A股最便宜的股票:androidinvest.com/CNValueTop/ 便宜指数 = PE + PB + 股息 + ROE,四因子等权,数值越大代表越低估. 本策略只是根据最新的数据来选 ...

  8. centos7.x下环境搭建(一)--yum方式安装mysql5.7

    前两天因为数据库被黑客攻击,导致数据被删除,数据库被损坏,系统重新安装了一下,所以环境也需要重新再搭一遍,包括mysql.nodejs.git.nginx和redis的安装.由于之前安装的mysql安 ...

  9. 利用kibana学习 elasticsearch restful api (DSL)

    利用kibana学习 elasticsearch restful api (DSL) 1.了解elasticsearch基本概念Index: databaseType: tableDocument: ...

  10. 关于多个版本的jquery冲突的问题

    关于多个版本的jquery冲突的问题 先加载新的版本jquery 然后使用no confi代码,直接上代码看效果 <script src="https://libs.baidu.com ...