当前位置: 首页 > news >正文

树形DP

以下当前点为\(u\)\(v\)\(u\)的儿子

为什么树上可以用DP?

每棵树代表着一个大问题,而其中的子树就是子问题

统一思想

每个点/边/子树代表着一个问题的解,先把子树的解求出以求出包含该子树的子树的解。

对于以点为对象的DP

最大独立集

模版问题描述(仅类似)

在一棵树上有若干个点,而每个点有一个权值,求选出若干个不相邻的点的权值的最大和。

解决方式

状态定义

$ Dp_{u,0/1} $ 表示当前结点u不选/选的子树的最大和。

状态转移

当该结点被选了时,那么就不选他的儿子,即

\[\text{dp}_{u,1}=val_u\;+\sum_{v\in son_u}\text{dp}_{v,0} \]

当该结点被没被选了时,那么就取选/不选中的最大值

\[\text{dp}_{u,1}=\sum_{v\in son_u}max(\text{dp}_{v,0},\text{dp}_{v,1}) \]

代码实现

void dfs(int u) {dp[u][0] = 0, dp[u][1] = val[u];for (auto v : g[u]) {dfs(v);dp[u][0] += max(dp[v][0], dp[v][1]), dp[u][1] += dp[v][0];}
}

最小支配集(覆盖与被覆盖)

DP做法

问题描述

每个顶点可以放置守卫,保护自己及相邻的节点。求最少需要选择多少个顶点放置守卫,使得树上所有节点都被保护。

解决方式

状态定义

\(\text{dp}_{u,0}\) 表示\(u\)被选中(\(u\)可以覆盖自己及子节点)。

\(\text{dp}_{u,1}\) 表示\(u\)被子节点保护(\(u\)没选,但至少有一个儿子被选了)。
\(\text{dp}_{u,2}\) 表示\(u\)被父节点保护(\(u\)没选,等父节点来保护)。

状态转移

\[\text{dp}_{u,0}=1+\sum_{v\in son_u}min(\text{dp}_{v,0},\text{dp}_{v,1},\text{dp}_{v,2}) \]

\[\text{dp}_{u,2}=1+\sum_{v\in son_u}min(\text{dp}_{v,0},\text{dp}_{v,1}) \]

$ \text{dp}_{u,1} $ 相对难想,需要在计算完其余两个时再求,但也可以就一起求。
在循环时同时求一个最小值\(minx\)

\[minx = min(-min(\text{dp}_{v,0},\text{dp}_{v,1}) + \text{dp}_{v,0}) \]

在最后可得

\[\text{dp}_{u,1}=\text{dp}_{u,2}+minx \]

代码实现
void dfs(int u, int fa) {dp[u][0] = 1;int minx = INF;for (auto v : g[u]) {if (v == fa) continue;dfs(v, u);dp[u][0] += min({dp[v][0], dp[v][1], dp[v][2]});dp[u][2] += min({dp[v][0], dp[v][1]});minx = min(-min(dp[v][0], dp[v][1]) + dp[v][0], minx);}dp[u][1] = dp[u][2] + minx;
}

贪心做法

每个点要么自己保护自己,要么被别人保护。(相当于该点一定要被保护)
那么,对于 深度最深(叶子结点) 的点来说,可以保护他的有两个情况: 自己,自己的父亲。
贪心的考虑,显然选择父节点要更好一些。

  • 每次选择深度最深的点,放在他的父亲。
  • 如果不存在父亲,那么就放在自己身上。

贪心的缺陷

贪心只能解决每个点的代价相同的问题,不能解决每个点的代价不同的问题。

对于以边为对象的DP

最小点覆盖

形象化题意

给定一棵无根树,士兵驻扎在点上,驻扎在 x 点的士兵可以看守所有与 x 相邻的边,
请问守住所有的边至少需要多少士兵?

解决方式

状态定义

\(\text{dp}_{u,0/1}\) 表示分别以\(u\)为根的子树在点\(v\)不放置/放置士兵。

状态转移

\[\text{dp}_{u,0} = \sum_{v \in son_u}\text{dp}_{v,1} \]

\[\text{dp}_{u,1} = 1 + \sum_{v \in son_u}min(\text{dp}_{v,0},\text{dp}_{v,1}) \]

代码实现

void dfs(int u, int fa) {dp[u][1] = 1;for (auto v : g[u]) {if (v == fa) continue;dfs(v, u);dp[u][0] += dp[v][1], dp[u][1] += min(dp[v][0], dp[v][1]);}
}

最大匹配

形象化题面

\(n\)个人组队打比赛,每队两个人,一共给了\(n-1\)组组队意向,请求出保证满足以下条件的组队方式:

  1. 一个人只能待在一个队伍
  2. 只能根据组队意向组队

解决方式

挺好想的,自己先想想。

实现代码

void dfs(int u, int fa) {for (auto v : g[u]) {if (v == fa) continue;dfs(v, u);dp[u][0] += max(dp[v][0], dp[v][1]);}for (auto v : g[u]) {if (v == fa) continue;dp[u][1] = max(dp[u][1], dp[u][0] - max(dp[v][0], dp[v][1]) + dp[v][0] + 1);}
}

总结

还是挺简单的。_

http://www.jsqmd.com/news/334339/

相关文章:

  • 关于Locust的讲解
  • DeepSeek推广公司:为您的企业打造专业AI营销支持体系 - 品牌2026
  • 2026年 中央空调品牌实力推荐榜:开利/超静音/全直流变频/智能化,百年发明家品牌的能效与静音革命 - 品牌企业推荐师(官方)
  • 多智能体系统详解:AI开发的革命性模式,收藏必读!
  • 2026寒假训练3
  • 【系统分析师】6.4 企业信息系统
  • 图论专题(二十一):并查集的“工程应用”——拔线重连,修复「连通网络」 - 指南
  • 大模型开源+免费教程,推荐一波大模型图文教程、视频课程(附文档)
  • 必看!零代码实现RAG:Cherry Studio构建私有知识库教程,建议收藏
  • 国产CAD让设计到加工的数据不再“掉链子”
  • Postman
  • 《P3810 【模板】三维偏序 / 陌上花开》
  • AI方向的就业机会将集中在哪些岗位?春招应届生如何提前筹备?
  • 2026年 复印机打印机综合服务推荐榜:租赁销售维修批发一站式解决方案,专业设备与高效服务口碑之选 - 品牌企业推荐师(官方)
  • 申报国自然,如何打破信息差?
  • Avalonia MVVM
  • 基于Kubernetes的AI多租户系统部署实战
  • LazyLLM教程 | 第4讲:RAG项目工程化入门:从脚本走向模块化与可维护性
  • AI Agent规划能力实战:点餐支付售后多任务协同实现,面试官看了都点头!建议收藏
  • 毕业论文盲审在即,现在还没动笔?
  • LLM教程 | 第2讲:10分钟上手一个最小可用RAG系统
  • VLA Notes - kirin
  • 【笔记】【图】
  • 通过 C# 设置 Word 文档背景颜色、背景图
  • 通用 Agent 执行沙箱环境技术方案调研报告
  • LLM教程 | 第1讲:RAG原理解读:让检索增强生成不再是黑盒
  • 2026年圆形、防水与密封连接器厂家三维测评与选型指南 - 品致汇
  • 小白从零开始勇闯人工智能:计算机视觉初级篇(OpenCV补充(1))
  • 【SRC】抓包环境搭建与并发漏洞实战全解
  • 雷鸟创新背着10亿闯三关