树形DP通用思路总结

news/2025/10/30 15:52:39/文章来源:https://www.cnblogs.com/xihegudi/p/19177278

树形 DP 的通用套路就是定根 → 设状态(含语义与边界)→ 按子树合并转移,再用 换根(rerooting)/树形背包/计数与期望等模板覆盖高频题型,必要时配合小到大合并、长链剖分或虚树解决复杂度问题。

一、通用三步法?

  1. 定根:任选 1 为根(或题意指定/重心/直径端点),把无根树变成有根树。
  2. 设状态:让 dp[u][*] 的每一维都有清晰语义(如选/不选、已用容量、涂色数、路径是否经过 u 等),明确可空子树的返回值(常用 0、1、−INF)。
  3. 合并转移:对子节点逐个合并(“多子树分组背包”),注意顺序与幂等
    • 点/边独立:min/max + Σ child 型。
    • 路径/距离:size、sum 两件套;
    • 树形背包:二维/一维滚动合并,复杂度常见 O(n k^2),用“大合并小/分治/单调性”优化。

二、典型模型与“拿来即用”的状态设计

1. 点独立集 / 覆盖 / 匹配(最常考)

  • 最大独立集f[u][0/1] 表示 u 不选/选 的最优。 转移:f[u][1] = val[u] + Σ f[v][0]``f[u][0] = Σ max(f[v][0], f[v][1])
  • 最小点覆盖最大匹配互补;边版本同理改成边状态或儿子之间两两配对。

2. 距离与路径贡献

  • 子树信息sz[u] 子树大小,g[u] 为 u 到其子树所有点距离和:g[u] = Σ (g[v] + sz[v])
  • 换根(全局距离和)ans[1]=g[1],向下:ans[v] = ans[u] + n - 2*sz[v]。 同构思可做经过 u 的路径数/长度和点/边权累加等。

3. 树形背包

  • f[u][j] 表示在 u 的子树拿 j 个(或容量 j)能取得的最优。
  • 合并孩子时做分组背包:f[u]= merge(f[u], f[v]),双循环 jt
  • 常见优化:
    • 大合并小把均摊复杂度降到 O(n k)
    • 若转移是 min-convolution,可用分治/单调队列/Knuth等(依题目结构)。

4. 染色与计数(方案数 / 期望)

  • 树上 k 染色(相邻不同色):f[u] = (k-1) * Π f[v] 或用 f[u][same/diff] 细分。
  • 计数题注意:模数、空子树=1,与乘法在合并时机

5. Rerooting(换根 DP)

把“以 u 为根的答案”设为聚合函数:

  • 自底向上得到每条“向父贡献”的值;
  • 用前后缀预处理(或 AtCoder 式模板)把去掉某子树的外部贡献 O(1) 拿到,再把根换到该子树。 适用:距离和、最大值带方向、子树答案转全局答案、边双向属性等。

6. 进阶

  • DSU on tree(小到大):离线统计“关于 u 子树的查询”(颜色数、频次、莫队思想),不是 DP,但常与“每个 u 的答案”搭配。
  • 虚树 DP:关键点集上的 DP,把原树缩成含关键点与其 LCA 的稀疏树,复杂度 O(k log n) 建 + O(k) DP。
  • 长链剖分:把线性转移挂到主链上,优化合并。
  • 答案二分 + 可行性 DP:如“最多选 k 条边使代价 ≤ X”。

三、合并技巧与复杂度

  • 两层循环谁在外? 通常“容量/数量在外,孩子在内”。
  • 大合并小:总移动次数 ≤ 每元素被搬运 O(log n) 次,降维打击树背包的常数。
  • 前后缀:把“去掉某个孩子的合并结果” O(1) 取到,为换根模板与“除去某子树的贡献”提供捷径。
  • 空集定义:计数设 1,max 设 -INF,min 设 +INF,避免把“没选到东西”的状态误参与比较。

四、易错

  • 点权/边权别混:统一在转移的入口处“落点”。
  • 模数:乘法合并先取模;0 方案注意。
  • 重根时别二次计入ans[v] = ans[u] + … - 子树贡献 + 外部贡献,公式要写干净。
  • 空子树/叶子:提前给初值;max 型要允许“一个孩子也不选”。
  • 递归深度:极端链用迭代或 std::vector<int>().shrink_to_fit() 无关,这里更建议栈大小尾递归的替代。

五、模板

1) 最大独立集(点权)

// 题意&思路:树上选点,任意相邻不能同选;dp[u][0/1] 表示不选/选u的最优。
// 转移:选u则孩子必不选;不选u则孩子取max。
// 复杂度O(n)。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=200005;int n,hd[N],to[N<<1],nx[N<<1],ec;
ll w[N],f[N][2];void ad(int u,int v){ to[++ec]=v; nx[ec]=hd[u]; hd[u]=ec; }
void df(int u,int p){f[u][1]=w[u];for(int e=hd[u];e;e=nx[e]){int v=to[e]; if(v==p) continue;df(v,u);f[u][1]+=f[v][0];f[u][0]+=max(f[v][0],f[v][1]);}
}
int main(){ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin>>n;for(int i=1;i<=n;i++) cin>>w[i];for(int i=1,u,v;i<n;i++){ cin>>u>>v; ad(u,v); ad(v,u); }df(1,0);cout<<max(f[1][0],f[1][1])<<"n";
}

2) 距离和(换根 DP)

// 题意&思路:求每个点到所有点的距离和。先算子树距离和g与子树大小sz;
// 再换根:ans[v]=ans[u]+n-2*sz[v]。总O(n)。
#include<bits/stdc++.h>
using namespace std; 
using ll=long long;
const int N=200005;int n,hd[N],to[N<<1],nx[N<<1],ec,sz[N];
ll g[N],ans[N];void ad(int u,int v){ to[++ec]=v; nx[ec]=hd[u]; hd[u]=ec; }
void d1(int u,int p){sz[u]=1; g[u]=0;for(int e=hd[u];e;e=nx[e]){int v=to[e]; if(v==p) continue;d1(v,u);sz[u]+=sz[v];g[u]+=g[v]+sz[v];}
}
void d2(int u,int p){for(int e=hd[u];e;e=nx[e]){int v=to[e]; if(v==p) continue;ans[v]=ans[u]+(ll)n-2*sz[v];d2(v,u);}
}
int main(){ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin>>n;for(int i=1,u,v;i<n;i++){ cin>>u>>v; ad(u,v); ad(v,u); }d1(1,0); ans[1]=g[1]; d2(1,0);for(int i=1;i<=n;i++) cout<<ans[i]<<(i==n?'n':' ');
}

六、思考什么?

  • 我需要子树信息还是全局每点答案?若后者,十有八九要 rerooting

  • 状态是否可合并且无顺序依赖?若有顺序依赖,考虑前后缀链式优化

  • 是否存在“选/不选”二值语义?能否把复杂约束转化为“选了谁就限制谁”的树独立/覆盖模型?

  • 复杂度落在 O(n) / O(n log n) / O(n k) 可承受区间了吗?不行就:大合并小 / 降维 / 分治 / 单调。

  • 边界:空子树值、模数、叶子初始化、取 max/min 的“无效值”。

    模型/目的 状态设计(示例) 合并与转移 常见复杂度 易错点
    最大独立集 f[u][0/1] 选 u:儿子取 0;不选:取 max O(n) 重复计数、负权初值
    最小覆盖/匹配 f[u][0/1/2] 或边匹配 相邻限制 + 枚举儿子态 O(n) 覆盖定义与可行性
    距离/路径和 sz[u], g[u] g[u]=Σ(g[v]+sz[v]);换根 ans[v]=ans[u]+n-2sz[v] O(n) sz 与方向号
    树形背包 f[u][j] 儿子分组背包合并 O(n k^2) → 优化到 O(n k) 空集初值、转移顺序
    染色/计数 f[u]f[u][same/diff] 乘法合并 O(n) 模数与 0/1 设定
    Rerooting 子树 DP + 前后缀 去掉某子树的外部贡献再加回 O(n) 不要重复计入

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/950900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年深圳货车锂电池回收公司权威推荐榜单:沃特玛电池回收/力神锂电池回收 /测试车锂电池回收源头公司精选

深圳作为中国新能源汽车产业发展的核心区域,已构建了完善的动力电池回收网络体系,为货车锂电池回收提供了强有力的支撑。 在新能源汽车产业快速发展的背景下,深圳作为全国新能源技术创新的前沿阵地,其货车锂电池回…

2025年知名的超微粉碎机厂家推荐及选择参考

2025年知名的超微粉碎机厂家推荐及选择参考行业概述超微粉碎技术作为现代粉体加工的核心工艺,在食品、医药、化工、新材料等领域发挥着越来越重要的作用。随着2025年制造业智能化升级的加速推进,超微粉碎机行业也迎来…

2025年11月份国内台球杆厂家推荐榜:台球杆、NVS球杆、手工杆实力品牌优选

在台球运动蓬勃发展的当下,台球杆市场也呈现出繁荣的景象。优质的台球杆不仅能够提升击球的精准度和控制力,还能让玩家在击球过程中感受到更好的手感和反馈。接下来,我们将为您深度解析,并推荐相关优质企业。TOP1推…

2025年质量好的木材单板烘干机厂家推荐及选择指南

2025年质量好的木材单板烘干机厂家推荐及选择指南开篇介绍在木材加工行业中,单板烘干是决定最终产品质量的关键环节之一。随着2025年木材加工技术的不断进步,高效、节能、智能化的单板烘干设备已成为行业标配。优质的…

2025年江苏老酒回收服务商权威推荐榜单:洋酒回收/虫草回收/整箱茅台回收服务商精选

随着陈年名酒收藏市场的持续升温,江苏省老酒回收行业呈现规范化、专业化发展趋势。据江苏省酒类收藏协会2024年数据显示,全省老酒交易规模较上年增长28%,其中高端名酒回收业务占比达42%,茅台、五粮液等一线名酒保值…

基于英飞凌MCU实现BLDC无感正弦波FOC控制

一、硬件架构设计 1.1 硬件组成 // 英飞凌XMC1300系列MCU资源分配 #define PWM_FREQ 16000 // PWM频率16kHz #define ADC_SAMPLING 1000 // 1kHz采样率 #define VDC 24.0f // 直流母线…

显式求解三维温度场并输出Tecplot文件的C++实现

1. 主程序头文件和参数定义 // thermal_solver_3d.h #ifndef THERMAL_SOLVER_3D_H #define THERMAL_SOLVER_3D_H#include <vector> #include <string> #include <fstream> #include <iostream>…

哈希重温

字符串哈希(进制哈希)把字符串通过哈希函数映射成一个数,类似进制的方法处理即可。 下文我们约束字符串为 $str$,长度分别为 $n$,以 $1$ 为起始下标。 类比成 $base$ 进制的理解,有: $$hash(str)=\sum_{i=1}^{n…

.NET6 Web程序部署在IIS上

1、应用程序在IDE中进行发布 2、需要在Window 服务器上开启IIS 3、ASP.NET Core 应用针对IIS部署依赖于一个IIS针对ASP.NET Core的扩展模块。所以需要下载ASP.NET Core 运行时的Hosting Bundle。ASP.NET Core ModuleAS…

20251030模拟赛

T1 小模拟题,场切了。

HarmonyOS自动化测试与持续集成实战指南

1. 自动化测试概述与工具链介绍 自动化测试是HarmonyOS应用开发流程中保证质量的关键环节。随着HarmonyOS生态的快速发展,应用功能日益复杂,分布式特性、多设备适配需求以及快速迭代的开发模式,使得传统手动测试无法…

HarmonyOS应用性能调优与内存管理实战

1. 性能优化概述与指标体系 性能优化是HarmonyOS应用开发中不可或缺的一环,它直接影响用户体验和应用稳定性。一个高性能应用应具备快速启动、流畅交互和低资源消耗等特点。在HarmonyOS应用性能评估中,我们需要关注几…

GEO优化源头厂家怎么选?这篇干货帮你摸透门道!

最近不少老板都在问:“GEO优化到底是个啥?源头厂家哪家强?” 别急,咱们今天就用大白话,掰开揉碎了聊一聊,顺便给大家推荐一个实力派选手——讯灵AI(GEO+Agent)双引擎系统。 一、GEO是啥?为啥它成了香饽饽? 简单…

HarmonyOS大型项目架构与模块化开发指南

1. HarmonyOS大型项目架构设计 HarmonyOS大型项目开发需要采用分层架构和模块化设计,确保代码的可维护性、可扩展性和团队协作效率。合理的架构设计是项目成功的基础。 1.1 分层架构设计原则 HarmonyOS推荐采用四层架…

鸿蒙NDK开发实战指南:从ArkTS到C/C++的高性能桥梁

1. NDK概述与核心价值 HarmonyOS NDK(Native Development Kit)是HarmonyOS SDK中提供的Native API、编译脚本和编译工具链的集合,它让开发者能够使用C或C++语言实现应用的关键功能模块。NDK主要覆盖了HarmonyOS的基…

HarmonyOS后台任务管理:短时任务与长驻任务实战

一、HarmonyOS后台任务概述 HarmonyOS的后台任务管理旨在平衡任务执行需求与系统资源消耗,提供多种后台任务类型以满足不同场景的需求。后台任务主要分为短时任务和长驻任务两大类,每种类型都有特定的使用场景和限制…

GEO 源头厂家独家王炸:南方网通讯灵 AI 业内首创“3+4+3” 智能生态营销体系,领爆AI搜索新浪潮

近日,深圳彻底沸腾!一场聚焦GEOAI 搜索时代的“流量破局盛会”高能集结 —— 这不是普通行业会,而是专门为 “苦流量枯竭久矣” 的企业主量身定制的增长急救场! 现场汇聚了200+企业掌舵人,他们带着各自行业的实战…

HarmonyOS分布式硬件共享:调用手机摄像头的手表应用

一、分布式硬件共享概述 分布式硬件共享是HarmonyOS的核心能力之一,它基于分布式硬件池理念,将网络中多个物理设备的硬件资源进行统一虚拟化管理。这意味着应用程序可以按需调用任意可信设备的硬件能力,打破传统单设…

HarmonyOS应用配置文件与资源组织深度解析

一、应用程序包结构概述 HarmonyOS应用以APP Pack形式发布,它由一个或多个HAP以及描述每个HAP属性的pack.info组成。HAP是Ability的部署包,可分为entry和feature两种类型。 Entry类型的HAP是应用的主模块,一个应用中…

OpenHarmony内核基础:LiteOS-M内核与POSIX/CMSIS接口

1. OpenHarmony内核架构概述 OpenHarmony采用多内核设计理念,根据设备资源能力匹配不同的内核形态,为各种物联网设备提供精准化的系统支持。这种设计使得OpenHarmony能够灵活适应从低端资源受限设备到高端智能设备的…