[模版]最大子树和 题解

[模版]最大子树和 题解

前置芝士

树上DP

题目大意

给出一棵树,上面有权值, 求这个数的子树的最大权值和。

模板题,就是树上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;
}
posted @ 2022-02-11 15:40  落花月朦胧  阅读(99)  评论(0编辑  收藏  举报