P1122 最大子树和
解题思路
这道题目可以转化为在树上寻找一个连通子图,使得该子图中所有节点的美丽指数之和最大。由于题目允许通过修剪枝条(即删除边)来得到不同的子树,我们需要找到所有可能的子树中美丽指数和最大的那个。
关键点
-
树形DP:使用深度优先搜索(DFS)遍历树,计算以每个节点为根的子树的最大美丽指数和。
-
状态转移:对于每个节点,其最大美丽指数和可以是自身值,或者自身值加上所有子节点的最大美丽指数和(如果子节点的贡献为正)。
-
全局最大值:在计算完所有节点的最大美丽指数和后,取其中的最大值作为最终结果。
注意事项
-
树的存储使用邻接表。
-
需要避免重复访问父节点,防止形成环路。
-
初始化时,每个节点的最大美丽指数和为其自身的值。
代码注释
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; // 定义最大节点数,比题目要求的16000大一些 vector<int> g[N]; // 邻接表,存储树的边关系 int n,m; // n表示花的数量,m未使用可以删除 int a[N]; // 存储每朵花的美丽指数 int f[N]; // 存储每个节点的父节点,实际未使用可以删除 int w[N],v[N],dp[N]; // w和v未使用可以删除;dp[x]表示以x为根的子树的最大美丽指数和 // DFS遍历树,计算以x为根的子树的最大美丽指数和 void dfs(int x,int fa) { f[x] = fa; // 记录父节点,实际未使用可以删除 dp[x] = a[x]; // 初始化dp[x]为当前节点的美丽指数 for(int i = 0; i < g[x].size(); i++) // 遍历所有子节点 { int y = g[x][i]; // 子节点y if(y == fa) continue; // 避免回溯到父节点 dfs(y,x); // 递归处理子节点 // 状态转移:如果子节点的贡献为正,则加上子节点的dp值 dp[x] = max(dp[x], dp[x] + dp[y]); } } int main() { cin >> n; // 输入花的数量 for(int i = 1; i <= n; i++) cin >> a[i]; // 输入每朵花的美丽指数 for(int i = 1; i < n; i++) // 输入n-1条边 { int x,y; cin >> x >> y; g[x].push_back(y); // 无向图,双向加边 g[y].push_back(x); } dfs(1,0); // 从根节点1开始DFS遍历,初始父节点为0 int ans = -1e9; // 初始化答案为负无穷 for(int i = 1; i <= n; i++) ans = max(ans,dp[i]); // 遍历所有节点,找到最大的dp值 cout << ans; // 输出结果 return 0; }

浙公网安备 33010602011771号