题目传送门

题解
- 比较简单的换根DP,很容易想到。
- 我们可以维护
d
p
[
i
]
:
dp[i]:
dp[i]: 以i为根的子树中最长的链(不包括节点i的值)。
- 对于任意结点
u
u
u ,我们需要子树中 最长的链mmx 和 次大的链mx
- 那么我们可以每次处理完节点
u
u
u 的子树后,更新
a
n
s
=
m
m
x
+
m
x
+
d
p
[
u
]
ans = mmx + mx + dp[u]
ans=mmx+mx+dp[u],然后更新
d
p
[
u
]
=
m
m
x
dp[u]=mmx
dp[u]=mmx。
- 由于避免
d
p
[
i
]
dp[i]
dp[i] 所表示的链断开而错误,我们在初始化
m
m
x
=
i
结
点
的
v
a
l
mmx=i结点的val
mmx=i结点的val,这样就可以保证,对于子树中的dp[i]表示的一定是和
i
i
i 结点连续的链。
- 注意:太久没碰过题了,导致连初始化都不记得做。vector直接爆内存了。然后注意ans初始化为-INF。C++不关闭流同步可能导致超时。
AC-Code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 7;
const int INF = 0x3f3f3f3f;
struct NODE {
int to;
int val;
NODE(int t, int v) : to(t), val(v) {}
};
vector<NODE>G[maxn];
int dp[maxn];
int ans;
void add(int u, int v, int val) {
G[u].push_back(NODE(v, val));
G[v].push_back(NODE(u, val));
}
void dfs(int u, int fa) {
int mmx = dp[u], mx = -INF;
for (int i = 0; i < G[u].size(); ++i) {
if (G[u][i].to == fa) continue;
int v = G[u][i].to, val = G[u][i].val;
dfs(v, u);
mx = max(mx, val + dp[v]);
if (mx > mmx) swap(mmx, mx);
}
ans = max(ans, mx + mmx);
dp[u] = mmx;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t; cin >> t;
while (t--) {
int n; cin >> n;
for (int i = 1; i <= n; ++i)
G[i].clear();
ans = -INF;
for (int i = 2; i <= n; ++i) {
int a, b; cin >> a >> b;
add(i, a, b);
}
for (int i = 1; i <= n; ++i)
cin >> dp[i];
dfs(1, -1);
cout << ans << endl;
}
}