【模板】树形dp

这篇博客探讨了树形动态规划在解决存储、子树大小、节点深度、树的重心、子树最长链与次长链以及每个点到其他结点距离和等问题上的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

存储

#include <bits/stdc++.h>
using namespace std;
#define size 100001
struct edge
{
   
   
    int to, nt, v;
} e[2*size];
int lst[size], cnt = 0;
inline void add( int u, int v, int w )
{
   
   
	cnt++;
	e[cnt].to = v;
	e[cnt].nt = lst[u];
	e[cnt].v = w;
	lst[u] = cnt;
}

子树大小+节点深度

int siz[size], dep[size];
inline void dfs( int x, int f, int d )
{
   
   
	siz[x] = 1;
	dep[x] = d;
	for ( 
### 关于C++中的树形动态规划(Tree DP树形动态规划是一种基于图论的算法设计技术,通常用于解决定义在树结构上的优化问题。这类问题的特点是输入数据可以表示为一棵无环连通图(即树),并且可以通过自底向上的方式计算最优解。 #### 树形DP的核心概念 树形DP的关键在于状态的设计以及如何通过子节点的状态来更新父节点的状态。常见的做法是从叶子节点开始逐步向上回溯,直到根节点完成整个树的状态转移过程[^1]。 以下是实现树形DP的一个通用模板: ```cpp #include <bits/stdc++.h> using namespace std; // 定义最大节点数 const int MAXN = 100005; vector<int> tree[MAXN]; // 邻接表存储树结构 long long dp[MAXN][2]; // 动态规划数组 void dfs(int u, int parent) { // 初始化当前节点的状态 dp[u][0] = 0; // 不选当前节点的情况 dp[u][1] = some_value(u); // 选当前节点的情况 for (auto &v : tree[u]) { if (v != parent) { // 跳过父节点 dfs(v, u); // 更新dp[u][0], 假设不选u,则可以从子节点任意选择 dp[u][0] += max(dp[v][0], dp[v][1]); // 更新dp[u][1], 假设选择了u,则不能选择其直接子节点 dp[u][1] += dp[v][0]; } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; // 构建树 for (int i = 1; i < n; ++i) { int a, b; cin >> a >> b; tree[a].push_back(b); tree[b].push_back(a); } // 开始DFS遍历 dfs(1, -1); cout << max(dp[1][0], dp[1][1]); // 输出最终结果 } ``` 上述代码展示了一个典型的树形DP实现流程。`dfs`函数负责递归访问每一个节点并填充动态规划表格 `dp` 的值。具体来说: - `dp[u][0]`: 表示不选取节点 `u` 时的最大收益。 - `dp[u][1]`: 表示选取节点 `u` 时的最大收益。 此模板可以根据实际问题调整状态定义和转移方程。 #### 学习资源推荐 对于希望深入学习 Tree DP 的开发者而言,以下是一些可能有帮助的学习材料或教程链接[^2]: - **LeetCode**: 提供大量有关树形DP的实际编程题目,例如“House Robber III”等问题可以直接练习该技巧。 - **Codeforces Blog Entries**: Codeforces社区中有许多高质量博客文章专门讨论各种类型的动态规划及其应用案例。 - **GeeksforGeeks Articles on Dynamic Programming over Trees**: 这里包含了详细的理论解释加上多个实例分析。 #### 注意事项 当处理大规模数据集时需注意效率问题;此外还需考虑边界条件如孤立点或者仅有单条边连接的小型测试样例是否会引发错误逻辑判断等情况发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值