题目描述
题目分析
对于求树的子区域最大和,考虑使用树形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;
}