Problem Description
Acesrc is a famous tourist at Nanjing University second to none. During this summer holiday, he, along with Zhang and Liu, is going to travel to Hong Kong. There are n spots in Hong Kong, and n−1 bidirectional sightseeing bus routes connecting these spots. They decide to visit some spots by bus.

However, Zhang and Liu have different preferences for these spots. They respectively set a satisfactory value for each spot. If they visit the ith spot, Zhang will obtain satisfactory value ai, and Liu will obtain bi. Starting with Zhang, they alternately decide the next spot to visit for the sake of fairness. There must be a bus route between the current spot and the next spot to visit. Moreover, they would never like to visit a spot twice. If anyone can't find such a next spot to visit, they have no choice but to end this travel.

Zhang and Liu are both super smart competitive programmers. Either want to maximize the difference between his total satisfactory value and the other's. Now Acesrc wonders, if they both choose optimally, what is the difference between total satisfactory values of Zhang and Liu?

 
Input
The first line of input consists of a single integer T (1≤T≤30), denoting the number of test cases.

For each test case, the first line contains a single integer n (1≤n≤105), denoting the number of spots. Each of the next two lines contains n integers, a1,a2,⋯,anand b1,b2,⋯,bn (0≤ai,bi≤109), denoting the 
satisfactory value of Zhang and Liu for every spot, respectively. Each of the last n−1 lines contains two integers x,y (1≤x,y≤n,x≠y), denoting a bus route between the xth spot and the yth spot. It is reachable from any spot to any other spot through these bus routes.

It is guaranteed that the sum of n does not exceed 5.01×105.

 
Output
For each test case, print a single integer in one line, the difference of total satisfactory values if they both choose optimally.
 
Sample Input
1
3
1 1 1
0 2 3
1 2
1 3
 
Sample Output
-1
 
题意:
给定一棵树,每个节点上对应两个权值,分别是两个人的满意度,他们两个都想让自己的满意度减去另外一个人的满意度之和尽可能大,求最终得到的值.
注意,这两个人交替选择方向,并且不能走回头路,由第一个人选择起始点.
(题意太复杂,说得不好请见谅)
思路:
树形dp,求出以1号节点为起始点时,每个点由第一个人和第二个人选择而来得到的最大值和次大值.
然后换根即可.
其中有很多地方需要注意,如如果一个点只有一个儿子结点或者本身是叶子结点时,需要特殊处理一下,因为在换根途中,切断其与父亲结点的关系之后,其最大值和最小值可能存在问题.
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime> #define fuck(x) cerr<<#x<<" = "<<x<<endl;
#define debug(a, x) cerr<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define lson l,mid,ls
#define rson mid+1,r,rs
#define ls (rt<<1)
#define rs ((rt<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int loveisblue = ;
const int maxn = ;
const int maxm = ;
const ll Inf = 0x3f3f3f3f3f3f3f3f;
const int mod = ;
const double eps = 1e-;
const double pi = acos(-); int Head[maxn], cnt;
struct edge {
int Next, v;
} e[maxm]; void add_edge(int u, int v) {
e[cnt].Next = Head[u];
e[cnt].v = v;
Head[u] = cnt++;
} ll a[maxn]; ll dp1[][maxn];//0由第一个人选择而来,1第二个选择而来
ll dp2[][maxn];//次
bool vis[maxn]; void dfs(int u, int fa) {
bool flag = true;
for (int k = Head[u]; k != -; k = e[k].Next) {
if (e[k].v == fa) {
continue;
}
dfs(e[k].v, u);
flag = false; ll tmp1 = dp1[][e[k].v];
ll tmp0 = dp1[][e[k].v]; //当前由第一个人选择而来的,那下一个一定由第二个人选择而来
if (tmp1 < dp2[][u]) { swap(tmp1, dp2[][u]); }
if (dp2[][u] < dp1[][u]) { swap(dp2[][u], dp1[][u]); } if (tmp0 > dp2[][u]) { swap(tmp0, dp2[][u]); }
if (dp2[][u] > dp1[][u]) { swap(dp2[][u], dp1[][u]); }
} vis[u] = flag;
//叶子节点的特殊处理
if (flag) {
dp1[][u] = ;
dp1[][u] = ;
}
if (dp1[][u] != Inf) dp1[][u] += a[u];
if (dp1[][u] != -Inf) dp1[][u] += a[u];
if (dp2[][u] != Inf) dp2[][u] += a[u];
if (dp2[][u] != -Inf) dp2[][u] += a[u];
} ll ans = -Inf; void dfs1(int u, int fa) { ll tmp0 = dp1[][fa];
ll tmp1 = dp1[][fa]; //如果父亲节点的最值是由u转移来的,那么就要利用次值换根
if (tmp0 == dp1[][u] + a[fa]) {
tmp0 = dp2[][fa];
}
if (tmp1 == dp1[][u] + a[fa]) {
tmp1 = dp2[][fa];
} //如果fa是只有u这一个儿子,并且fa==1时,才会出现这种情况
if (tmp1 == -Inf) {
tmp1 = a[fa];
}
if (tmp0 == Inf) {
tmp0 = a[fa];
}
tmp0 += a[u];
tmp1 += a[u]; //u是叶子节点,直接特判
if (vis[u]) {
ans = max(ans, tmp1);
}
//此段代码和dfs中的完全相同
if (tmp1 < dp2[][u]) { swap(tmp1, dp2[][u]); }
if (dp2[][u] < dp1[][u]) { swap(dp2[][u], dp1[][u]); } if (tmp0 > dp2[][u]) { swap(tmp0, dp2[][u]); }
if (dp2[][u] > dp1[][u]) { swap(dp2[][u], dp1[][u]); } ans = max(ans, dp1[][u]); for (int k = Head[u]; k != -; k = e[k].Next) {
if (e[k].v != fa)dfs1(e[k].v, u);
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
int n;
ans = -Inf;
cnt = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
Head[i] = -;
scanf("%lld", &a[i]);
dp1[][i] = dp2[][i] = Inf;
dp1[][i] = dp2[][i] = -Inf; }
for (int i = ; i <= n; i++) {
ll x;
scanf("%lld", &x);
a[i] -= x;
}
for (int i = ; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
add_edge(x, y);
add_edge(y, x);
}
dfs(, );
ans = dp1[][];
for (int k = Head[]; k != -; k = e[k].Next) {
dfs1(e[k].v, );
}
printf("%lld\n", ans);
}
return ;
}

对代码有问题可以留言

HDU 6662 Acesrc and Travel (换根dp)的更多相关文章

  1. HDU 6662 Acesrc and Travel 换根DP,宇宙最傻记录

    #include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=1e6+50; cons ...

  2. Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)

    题目链接 传送门 题意 两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次 ...

  3. [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]

    题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...

  4. 2018.10.15 NOIP训练 水流成河(换根dp)

    传送门 换根dp入门题. 貌似李煜东的书上讲过? 不记得了. 先推出以1为根时的答案. 然后考虑向儿子转移. 我们记f[p]f[p]f[p]表示原树中以ppp为根的子树的答案. g[p]g[p]g[p ...

  5. 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市

    P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...

  6. 小奇的仓库:换根dp

    一道很好的换根dp题.考场上现场yy十分愉快 给定树,求每个点的到其它所有点的距离异或上m之后的值,n=100000,m<=16 只能线性复杂度求解,m又小得奇怪.或者带一个log像kx一样打一 ...

  7. 国家集训队 Crash 的文明世界(第二类斯特林数+换根dp)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4827 ​ 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...

  8. bzoj 3566: [SHOI2014]概率充电器 数学期望+换根dp

    题意:给定一颗树,树上每个点通电概率为 $q[i]$%,每条边通电的概率为 $p[i]$%,求期望充入电的点的个数. 期望在任何时候都具有线性性,所以可以分别求每个点通电的概率(这种情况下期望=概率 ...

  9. codeforces1156D 0-1-Tree 换根dp

    题目传送门 题意: 给定一棵n个点的边权为0或1的树,一条合法的路径(x,y)(x≠y)满足,从x走到y,一旦经过边权为1的边,就不能再经过边权为0的边,求有多少边满足条件? 思路: 首先,这道题也可 ...

随机推荐

  1. MUI - myStorage在ios safari无痕浏览模式下的解决方案

    myStorage在ios safari无痕浏览模式下的解决方案 今天看到了这个帖子LocalStorage 在 Private Browsing 下的一个限制, 吓尿了,如果用户开启了无痕浏览,ap ...

  2. 从零学React Native之14 网络请求

    通过HTTP或者HTTPS协议与网络侧服务器交换数据是移动应用中常见的通信方式. node-fetch是RN推荐的请求方式. React Native框架在初始化项目时, 引入了node-fetch包 ...

  3. nodeJs学习-13 router

    const express=require('express'); var server=express(); //目录1:/user/ var routeUser=express.Router(); ...

  4. POJ - 1679_The Unique MST

    The Unique MST Time Limit: 1000MS Memory Limit: 10000K Description Given a connected undirected grap ...

  5. 《C程序设计语言》笔记(一)

    一:导言 1:printf中的格式化字符串: %ld                    按照long整型打印 %6d                   按照十进制整数打印,至少6个字符宽,不够的 ...

  6. React Native开源项目如何运行(附一波开源项目)

    学习任何技术,最快捷的方法就是学习完基础语法,然后模仿开源项目进行学习,React Native也不例外.React Native推出了1年多了, 开源项目太多了,我们以其中一个举例子.给大家演示下如 ...

  7. Python中的TCP三次握手和四次挥手过程

    tcp三次握手和四次挥手 首先先介绍什么是传输层: 1.三次握手 1) 三次握手的详述 首先Client(客户)端发送连接请求报文,Server(服务器)段接受连接后回复ACK报文,并为这次连接分配资 ...

  8. vue单页面项目返回上一页无效,链接变化了,但是页面没有变化

    在最近的项目中,返回上一页没有效果,经过好久的排查才发现问题,是路由守卫写法不规范导致. 在项目中用路由守卫做了登录拦截,没登录的跳转到登录页面.页面跳转和拦截都没问题,但是返回上一页就不行了,也没有 ...

  9. android service中stub作用是什么?

    AIDL(android 接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互.如果你需要在一个进程中(例如:在一个Activit ...

  10. @loj - 2288@「THUWC 2017」大葱的神力

    目录 @description@ @solution@ @data - 1@ @data - 2@ @data - 3@ @data - 4@ @data - 5@ @data - 6@ @data ...