题目传送门
题解
- 比较简单的换根DP,很容易想到。
- 我们可以维护
- 对于任意结点
,我们需要子树中最长的链mmx和次大的链mx
- 那么我们可以每次处理完节点
的子树后,更新
,然后更新
。
- 由于避免
所表示的链断开而错误,我们在初始化
,这样就可以保证,对于子树中的dp[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]; // dp[i]:i子树价值最大链
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;
}
}