rt
@
HDU第八场
HDU6662 Acesrc and Travel 树形DP
题意:
- A,B两个人,每个节点有两个属性(a_i,b_i),A先选一个节点,B选相邻下一个节点,交替选直到没法选。A想让(sum (a_i-b_i))最大,B想让(sum (b_i-a_i))最大。两人都足够聪明,问最后(sum (a_i-b_i))是多少。
分析:
- 上面规矩的意思可以说:B想让(sum (a_i-b_i))最小,A想让(sum (b_i-a_i))最小。
- A选了(u),若此时(u)的儿子全是叶子,B肯定会帮A选(sum (b_i-a_i))最大的路径,此贡献是(a_u-b_u- max(sum (b_i-a_i))),这也是(sum (a_i-b_i))最小的路径。
- B选了(u),若此时(u)的儿子全是叶子,A肯定会帮B选(sum (a_i-b_i))最大的路径,此贡献是(a_u-b_u+ max(sum (a_i-b_i))),这也是(sum (b_i-a_i))最小的路径。
- 记录(dp1[i][0])表示双方采取最优策略下(i)子树向下路径中(sum (a_i-b_i))的最小值,(dp1[i][1])为次小值;(dp2[i][0])表示双方采取最优策略下(i)子树向下中(sum (b_i-a_i))的最小值,(dp2[i][1])为次小值。
- 若以节点(x)为根开始做上面树形DP,则(dp1[x][0])为此时的答案。为统计出每个节点为根时的答案,我们先随便从一个点开始一遍树形DP,然后从同一点开始做换根DP(也就是用父亲的信息更新自己作为根时的贡献。
- 转移方程:(dp1[u][0] = ar[u]-br[u] - max(dp2[v][0]); vin son[u]),(dp2[u][0] = ar[u]-br[u] - max(dp1[v][0]); vin son[u])
- 换根DP时:双方最优策略下:对每个节点记录它向上路径中最小的(sum(a_i-b_i))=TMP[u],min(dp1[u][0],TMP[u])是u为根时的答案。
- 为记录TMP[u]还需记录sta[u]表示u节点向上路径中最大的(sum(a_i-b_i)).
/*
在AB足够聪明的情况下,A要a-b最大值,答案是dp1[u][0]=min(sum (a_i-b_i)) = ar[u]-br[u]-dp2[u][0],在u的儿子中减去min(sum b_i-a_i)也就是加上max(sum a_i-b_i)),用最大的sum a_i-b_i更新答案即可。dp2[u][0]也是用最大的$sum b_i-a_i$更新答案。
换根DP时:双方最优策略下:对每个节点记录它向上路径中最小的$sum(a_i-b_i)$=TMP[u],min(dp1[u][0],TMP[u])是u为根时的答案。
为记录TMP[u]还需记录sta[u]表示u节点向上路径中最大的$sum(a_i-b_i)$.
本题用最大值来更新最小值,和用最小值来更新最大值,答案是最小值,这有点博弈感觉把。
*/
const int MXN = 1e6 + 7;
const int MXE = 1e6 + 7;
int n, m;
LL ar[MXN], br[MXN];
vector<int> mp[MXN];
LL dp1[MXN][2], dp2[MXN][2], TMP[MXN];
int son[MXN][2], fa[MXN], num[MXN];
LL ans;
void dfs1(int u, int ba) {//a - b的minsum, b - a的minsum
dp1[u][0] = dp1[u][1] = INFLL;
dp2[u][0] = dp2[u][1] = INFLL;
fa[u] = ba;num[u] = 0;
for(auto v: mp[u]) {
if(v == ba) continue;
dfs1(v, u);
num[u]++;
if(ar[u] - br[u] - dp2[v][0] < dp1[u][0]) {
son[u][0] = v;
dp1[u][1] = dp1[u][0];
dp1[u][0] = ar[u] - br[u] - dp2[v][0];
}else dp1[u][1] = sml(dp1[u][1], ar[u] - br[u] - dp2[v][0]);
if(br[u] - ar[u] - dp1[v][0] < dp2[u][0]) {
son[u][1] = v;
dp2[u][1] = dp2[u][0];
dp2[u][0] = br[u] - ar[u] - dp1[v][0];
}else dp2[u][1] = sml(dp2[u][1], br[u] - ar[u] - dp1[v][0]);
}
if(num[u] == 0) dp1[u][0] = dp1[u][1] = ar[u] - br[u], dp2[u][0] = dp2[u][1] = br[u] - ar[u];
}
LL tmp, sta[MXN];
void dfs2(int u, int ba) {
for(auto v: mp[u]) {
if(v == ba) continue;
tmp = dp1[v][0];
if(v == son[u][1]) {
tmp = dp2[u][1];
}else {
tmp = dp2[u][0];
}
int aim = 4;
// if(v == aim) debug(tmp, u, mp[u].size())
if(u != 1) tmp = sml(tmp, -sta[u]);//a-b max
if(num[u] == 1) {
if(num[v] == 0) ans = big(ans, TMP[v] = ar[v] - br[v] + sta[u]);
else ans = big(ans, sml(dp1[v][0], TMP[v] = ar[v] - br[v] + sta[u]));
// debug(u, v, ans, dp1[v][0], ar[v] - br[v], sta[u])
}
else {
if(num[v] == 0) ans = big(ans, TMP[v] = ar[v] - br[v] - tmp);
else ans = big(ans, sml(dp1[v][0], TMP[v] = ar[v] - br[v] - tmp));
}
// if(v == aim) debug(tmp, sta[u], mp[v].size())
if(v == son[u][0]) {
tmp = dp1[u][1];
}else {
tmp = dp1[u][0];
}// a-b max b-a min
if(num[u] == 1) sta[v] = ar[v] - br[v] + TMP[u];
else {
if(u == 1) sta[v] = ar[v] - br[v] + tmp;
else sta[v] = ar[v] - br[v] + sml(tmp, TMP[u]);//a-b max b - a min
}
// debug(u, v, ans, son[u][1]);
dfs2(v, u);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
// freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
int tim = read();
while(tim --) {
n = read();
for(int i = 1; i <= n; ++i) ar[i] = read(), mp[i].clear();
for(int i = 1; i <= n; ++i) br[i] = read();
for(int i = 1, a, b; i < n; ++i) {
a = read(), b = read();
mp[a].eb(b), mp[b].eb(a);
}
dfs1(1, 0);
for(int i = 1; i <= n; ++i) {
// printf("%d %d %lld %lld %lld %lld
", son[i][0], son[i][1], dp1[i][0], dp1[i][1], dp2[i][0], dp2[i][1]);
}
sta[0] = -INFLL;
TMP[1] = sta[1] = ar[1] - br[1];
ans = dp1[1][0];
dfs2(1, 0);//max minnum
printf("%lld
", ans);
}
#ifndef ONLINE_JUDGE
// cout << "time cost:" << 1.0*(clock())/CLOCKS_PER_SEC << "
";
#endif
return 0;
}
/*
6
7
-1 -1 -1 0 1 1 1
0 0 0 0 0 0 0
1 2
2 3
3 4
4 5
5 6
6 7
5
-100 1 -100 1 1
0 0 0 0 0
1 2
1 3
2 4
2 5
3
1 1 1
0 2 3
1 2
1 3
5
1 1 1 2 4
0 2 3 3 2
1 2
1 3
2 4
2 5
11
1 1 1 2 4 4 3 2 5 6 2
0 2 3 3 2 0 3 2 6 4 3
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
8 10
8 11
11
2 4 5 3 6 8 1 0 6 4 3
9 3 5 0 6 1 3 5 7 9 0
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
8 10
8 11
*/