题目描述


题目分析
对于求树的子区域最大和,考虑使用树形DP求解。
假设以树的某一结点为根节点来深度优先搜索整棵树,搜索到每个结点时都会有两种决策状态:加入该节点和不加入该节点。定义代表选择此结点所能得到最大权值和,
代表不选择此结点。叶子结点代表着边界状态:
状态转移方程为:
其中,表示当前结点的所有子结点。
需要注意,由于S可以为空集。当发现选择了任何策略的最大权值和均为负数时,答案输出0
由于答案可能超出整形返回,数据类型设为longlong。
此外,这棵树结点众多,使用邻接矩阵存储不合理,故使用邻接表来表示。
我的代码
第一次提交有部分测试数据未通过,经检查发现dfs函数的返回值也要写longlong。为了避免再次发生这种错误,直接定义Int为longlong了。
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#define int long long
using namespace std;
const int MAX_N = 100005;
int n;
int value[MAX_N];
vector<int> edge[MAX_N]; //邻接表 
int dp[MAX_N];
int marked[MAX_N]; //是否已搜索过
//深度优先搜索 
int dfs(int s) {
	marked[s] = 1;
	int sum = value[s];
	for (int i = 0; i < edge[s].size(); i++)
	{
		int next_v = edge[s][i];
		if (marked[next_v] == 0) {
			sum += max(dfs(next_v),0LL);
		}
	}
	dp[s] = sum;
	return sum;
}
signed main()
{
	//输入 
	cin >> n;	//n个结点 
	for (int i = 1; i <= n; i++) {
		cin >> value[i];
	}
	int a;
	int b;
	for (int i = 1; i <= n - 1; i++) {
		cin >> a >> b;
		edge[a].push_back(b);
		edge[b].push_back(a);
	}
	//动态规划+搜索 
	dfs(1);
	//输出答案
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		ans = max(ans, dp[i]);
	}
	cout << ans;
	return 0;
}

















