点对最大值 (换根DP)
Posted lesning
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点对最大值 (换根DP)相关的知识,希望对你有一定的参考价值。
“科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛)
换根来一波
https://ac.nowcoder.com/acm/contest/5758/A
#include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn = 1e6 + 111; ll list[maxn]; struct Node { int p; ll len; int nxt; }G[2*maxn]; int head[maxn]; int z; void add(int x, int y,ll len) { G[++z].p = y; G[z].nxt = head[x]; G[z].len = len; head[x] = z; } ll dp[maxn];//最大 ll dp2[maxn];//第二大 int cal(int x, ll val) {//x节点放进去一个val if (val >= dp[x]) { dp2[x] = dp[x]; dp[x] = val; } else { if (val >= dp2[x]) { dp2[x] = val; } } return 0; } int de[maxn]; int dfs1(int x, int fa) { for (int i = head[x]; i; i = G[i].nxt) { int p = G[i].p; ll ln = G[i].len; if (p == fa) continue; dfs1(p, x); ll a = list[x] + ln + list[p]; ll b = dp[p] - list[p] + ln + list[x]; if (a > b) { cal(x, a); } else { cal(x, b); } } return 0; } int dfs2(int x, int fa) { for (int i = head[x]; i; i = G[i].nxt) { int p = G[i].p; ll ln = G[i].len; if (p == fa) continue; ll c = list[x] + list[p] + ln; if (de[p] == 1) { if (list[x] + ln + list[p] == dp[x]) {//在线上 ll a = dp2[x] - list[x] + ln + list[p]; a = max(a, c); cal(p,a); } else { ll a = dp[x] - list[x] + ln + list[p]; a = max(a, c); cal(p, a); } } else { if (dp[p] - list[p] + ln + list[x] == dp[x]|| dp[x] == list[p] + list[x] + ln) { ll a = dp2[x] - list[x] + ln + list[p]; a = max(a, c); cal(p, a); } else { ll a = dp[x] - list[x] + ln + list[p]; a = max(a, c); cal(p, a); } } dfs2(p, x); } return 0; } int n, m; int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 0; i <= n; i++) { head[i] = 0; de[i] = 0; dp[i] = -1e18; dp2[i] = -1e18; } z = 0; int x; ll len; int be, en; for (int i = 2; i <= n; i++) { scanf("%d %lld", &x, &len); add(x, i, len); add(i, x, len); de[x]++; de[i]++; } for (int i = 1; i <= n; i++) { scanf("%lld", &list[i]); //dp[i] = 2 * list[i]; } dfs1(1, -1); dfs2(1, -1); long long ans = -1e18; for (int i = 1; i <= n; i++) { ans = max(ans, dp[i]); } printf("%lld ", ans); } return 0; } /* 21312 11 1 2 1 2 4 4s 2 3 3 3 5 7 3 6 8 1 7 2 7 8 5 7 9 6 8 10 9 9 11 10 1 2 3 4 5 6 7 8 9 10 11 */
以上是关于点对最大值 (换根DP)的主要内容,如果未能解决你的问题,请参考以下文章
ABC222 F - Expensive Expense(树形dp换根)