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

换根 DP 简介

【换根 DP 简介】
● 换根 DP 是树形 DP 的一种重要技术,用于解决需要以树中‌不同节点为根‌分别计算答案的问题。其核心思想是在一次动态规划后,通过‌推导出换根时的状态转移公式‌,高效地计算出所有节点作为根时的结果,避免对每个根节点都进行一次 O(n) 的树形DP(那样总复杂度为 O(n²))。

● 对于大多数简单的树形 DP 问题,如计算子树大小、节点深度、简单路径统计等,算法通常对每个节点执行常数次操作,因此时间复杂度为 ‌O(n)‌。

● 换根 DP 通常遵循一个固定的两遍 DFS 流程:
(一)第一次 DFS(固定根,收集信息)‌
(1)任选一个节点(通常为 1 号节点)作为初始根。
(2)进行一次自底向上的树形 DP,计算以该节点为根时,各子树的状态信息。这些信息通常包括:子树大小(siz[u])、子树内节点到根的距离和(dis[u])、或其他与问题相关的子树最优解。
(二)第二次 DFS(换根,推导全局)‌
(1)这是算法的关键。基于第一次 DFS 得到的信息,从初始根节点开始,进行第二次 DFS。
(2)在遍历过程中,当从父节点 u 走向子节点 v 时,利用已知的以 u 为根时的全局答案 dp[u],推导出以 v 为根时的全局答案 dp[v]。
(3)这个推导过程就是 ‌“换根公式”‌,它分析了当根从 u 移到 v 时,哪些节点的贡献发生了变化(例如,深度增加或减少),并据此更新答案。

● 经典示例:所有节点到其他节点距离之和
代码详见:https://blog.csdn.net/hnjzsyjyj/article/details/157169859
这是一个最经典的换根DP问题,清晰地展示了换根公式的推导过程。
(1)问题‌:给一棵树,求以每个节点为根时,所有节点到该根节点的深度之和。
(2)定义‌:siz[u]:以 u 为根的子树中的节点数、dis[u]:以 u 为根时,所有节点到 u 的深度之和。

P3478_1

(3)步骤‌:
第一次 DFS‌:以节点 1 为根,计算 siz[u] 和初始的 dis[1]。
换根公式推导‌:当根从 u 换到其子节点 v 时,所有在 v 子树中的节点,到新根 v 的距离比到旧根 u 的距离‌减少1‌。这部分贡献总共减少 siz[v]。所有不在 v 子树中的节点(共 n - siz[v] 个),到新根 v 的距离比到旧根 u 的距离‌增加1‌。这部分贡献总共增加 n - siz[v]。
因此,dis[v] = dis[u] - siz[v] + (n - siz[v]) = dis[u] + n - 2 * siz[v]。
第二次 DFS‌:应用此公式,即可从 dp[1] 递推计算出所有节点的 dis[i]。

● 换根 DP 问题的数据量通常会超过 10^5,所以常需在代码中使用如下语句(https://blog.csdn.net/hnjzsyjyj/article/details/143176072),避免 TLE。

ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

当然,也可以使用“快读(https://blog.csdn.net/hnjzsyjyj/article/details/120131534)”函数,代码如下。

int read() { //fast readint x=0,f=1;char c=getchar();while(c<'0' || c>'9') { //!isdigit(c)if(c=='-') f=-1;c=getchar();}while(c>='0' && c<='9') { //isdigit(c)x=x*10+c-'0';c=getchar();}return x*f;
}


【换根 DP 的经典问题】
洛谷 P3478:STA-Station:https://blog.csdn.net/hnjzsyjyj/article/details/157169859
洛谷 P10962:Computer:https://blog.csdn.net/hnjzsyjyj/article/details/157177019
洛谷 P6419:Kamp:https://blog.csdn.net/hnjzsyjyj/article/details/157134513

 

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

相关文章:

  • 【毕业设计】基于机器学习的网络购物平台的智能推荐(源码+文档+远程调试,全bao定制等)
  • 强烈安利8个AI论文软件,本科生搞定毕业论文!
  • 强烈安利8个AI论文软件,本科生搞定毕业论文!
  • 第 470 场周赛Q2——3702. 按位异或非零的最长子序列
  • 文字标注旋转角度设置(防止文字倒立)
  • 储能辅助电力系统调峰的容量需求研究 Matlab代码
  • 咋的,寒假 1 个月学门黑客技术,难道很难吗?
  • 储能辅助电力系统调峰的容量需求研究 Matlab代码
  • 【Matlab】 CRC-8 计算数组Checknum
  • 拒绝“数据搬运工”:PostgreSQL 存储过程与函数实战指南
  • 2026年评价高的镀锌桥架,模压桥架,北方电缆桥架厂家行业优质推荐 - 品牌鉴赏师
  • 吐血推荐!本科生AI论文平台TOP10:开题报告文献综述全搞定
  • 开源版 Claude Code 杀疯了,怒斩 70k+ Star!!
  • 大数据毕设选题推荐:基于django的菜价可视化系统蔬菜销售分析与预测可视化系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • UVM-build_phase/run_phase的执行顺序及仿真调度
  • AL_ControlRes代码中文注释
  • Jetbrains全家桶自动破解
  • Makefile中 =、:=和 ?=的使用方法
  • 生成式软件制造--AI驱动的软件开发 - 教程
  • C++ 线程互斥锁 lock_guard
  • 大模型应用工程师崛起之路:从入门到年薪60万+的完整指南
  • 人工智能应用-机器视觉:绘画大师 04.​​​​​​​​​​​​​​基于风格迁移的绘画大师
  • C++ 实现【精准可控】内存占用测试工具(指定内存大小,实打实占用物理内存,亲测可用)
  • typescript-类的静态属性和静态方法
  • 解锁AI记忆新范式:人类情景记忆如何提升大模型性能
  • 人工智能应用-机器视觉:绘画大师 05.还原毕加索的隐藏画
  • 揭秘!提示工程架构师优化提示系统用户参与策略的关键技巧
  • 【教程4>第10章>第25节】基于FPGA的图像Robert变换开发——理论分析与matlab仿真
  • AAAI 2025论文分享|Agent4Edu:基于大语言模型生成式智能体的个性化学习模拟器
  • Node.js代码统计神器