树形 DP

【概述】

树形动态规划是在树的数据结构上的动态规划,在各个阶段呈现树状关系的时候可以采用树形 DP,其基本思想是由子节点的信息推出父节点的信息。

树形 DP 中,是通过以下 4 4 个树的特点来进行建图的

  1. n n 个点, n 1 n-1 条边的无向图,任意两顶点间可达
  2. 无向图中任意两个点间有且只有一条路
  3. 一个点至多有一个前趋,但可以有多个后继
  4. 无向图中没有环

【计算顺序】

计算顺序与线性动态规划的顺推、逆推相似,同样有两个方向:

  1. 叶 —> 根:在回溯时,从叶节点向上转移状态
  2. 根 —> 叶:在叶向根 DFS 一遍后(预处理),再重新向下获取答案

【表示方法】

树形 DP 还涉及到建图的问题,如果题目能很清晰的输入一个树,一般使用 vector<int> s[N],用 s [ i ] s[i] 来保存节点 i i 的所有儿子。

当树是一般树且涉及到权值时,一般采用链式存储法,即用结构体数组 e d g e edge 存边, e d g e [ i ] edge[i] 表示第 i i 条边, h e a d [ i ] head[i] 存以 i i 为起点的第一条边(在 e d g e edge 中的下标)

struct Node {
    int next;		//下一条边的存储下标
    int to;			//这条边的终点
    int w;			//权值
}edge[N*2];			//由于是无向图,因此要开2倍

若以点 i i 为起点的边新增了一条,则在 e d g e edge 中的下标为 j j ,那么 e d g e [ j ] . n e x t = h e a d [ i ] edge[j].next=head[i] ,然后 h e a d [ i ] = j head[i]=j ,即每次新加的边作为第一条边,最后倒序遍历即可。

int cnt;		//边的计数
void Add(int x, int y, int w)		//起点x, 终点y, 权值w
{
    edge[cnt].x = x;
    edge[cnt].w = w;
    edge[cnt].next = head[x];
    head[y] = cnt++;
}

遍历以 x x 为起点的边时,以 i i 开始为第一条边,每次指向下一条(以 1 -1 为结束标志)

memset(head, -1, sizeof(head));

for(int i = head[st]; i != -1; i = edge[i].next)
{
    ...
}

【计算方法】

树形 DP 的计算方法则与线性 DP 不同,线性 DP 一般采用传统迭代,而树是通过递归定义的,因此树形 DP 要递归来求解。

一般而言,树形 DP 常与背包问题结合起来,常用 d p [ n o d e ] dp[node] 表示的是以 n o d e node 为根的子树能得到的最优解, d p [ n o d e ] dp[node] 需要从 n o d e node 的子结点进行状态转移,由于 d p [ n o d e ] dp[node] 的状态是由它的儿子转移而来,因此可以将 n o d e node n n 个儿子看做 n n 个物品,对这 n n 个物品抉择得到最优的 d p [ n o d e ] dp[node] 就用到背包的思想。

当然,树形 DP 不止 n o d e node 这一维,第二维一般都是以题目给出的限制需要来,然后根据题意保存好状态,写出状态转移方程,递归的求解 d p [ r o o t ] dp[root]

【基本步骤】

1、若问题是一棵隐性树(不以树为直接背景,但各个阶段呈树状关系),则需要将问题转化为一棵显性树,并存储各阶段的树状联系。

2、根据题目要求与数据量,选择合适的树的存储方式。

  若节点数小于 5000 5000 ,一般选用邻接矩阵存储;若节点数大于 5000 5000 ,一般选用邻接表来存储(边要开到 2 N 2*N ,因为是无向图);若是二叉树或需要多叉转二叉,则可以用两个一维数组 b r o t h e r [ N ] brother[N] c h i l d [ N ] child[N] 来存储。

3、写出动归方程

  通过孩子和父亲之间的关系建立方程,根据要求选用 根 —> 叶 或 叶 —> 根 的计算方式。

【例题】

AcWing 285. 没有上司的舞会(入门):点击这里

发布了748 篇原创文章 · 获赞 113 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104409774
今日推荐