[模版]最大子树和 题解
[模版]最大子树和 题解
前置芝士
题目大意
给出一棵树,上面有权值, 求这个数的子树的最大权值和。
解
模板题,就是树上DP。
可以想到只要这个树的子树的权值大于0就可以选择,即加上这个权值。
所以这个DP的转移方程是 \(f_i=\sum_{i=1}^nf_{a_i}[{f_{a_i}}>0]\)
其中 \(n\) 表示这个子树大小,\(a_i\) 表示这个子树的子节点。
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 16010;
struct node {
int dis, next;
} edge[N << 1];
int head[N + 1], siz;
inline void add(int from, int dis) {
edge[++siz].dis = dis;
edge[siz].next = head[from];
head[from] = siz;
}
int f[N + 1];
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0), std::cout.tie(0);
int n;
std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> f[i];
}
for (int i = 1; i < n; i++) {
int u, v;
std::cin >> u >> v;
add(u, v); add(v, u);
}
int ans = -2147483647;
std::function <void(int, int)> dfs = [&](int u, int fa) {
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].dis;
if (v != fa) {
dfs(v, u);
f[u] += (f[v] > 0 ? f[v] : 0);
}
}
ans = std::max(ans, f[u]);
};
dfs(1, 0);
std::cout << ans << std::endl;
return 0;
}