树形dp
概述
树形dp是用来统计树上最值,以及树上计数问题的一种dp模型,每个状态由它的儿子转移过来
例题
树上最值统计
https://codeforces.ml/problemset/problem/1528/A
给定有n个节点的树,每个节点的权可选从l~r中的任何一个数值。
定义树的权值是所有边权的和,每条边的边权是边上两点点权差的绝对值。
求树权的最大值。
性质1 对于一个已经确定的点u,有一与它相连的点v,其中v的点权取值范围为(l, r)。边(u, v)取极值,当且仅当v取两个端点值,即l或r。
证明显然。
推论1 图中所有叶子可以当作是连接到点权为0的虚拟节点。
推论2 图中所有点权应取端点值。
于是有状态方程
d
p
[
u
]
[
0
]
=
m
a
x
(
d
p
[
v
]
[
0
]
+
a
b
s
(
l
[
v
]
−
l
[
u
]
)
,
d
p
[
v
]
[
1
]
+
a
b
s
(
r
[
v
]
−
l
[
u
]
)
)
dp[u][0] = max(dp[v][0] + abs(l[v] - l[u]), dp[v][1] + abs(r[v] - l[u]))
dp[u][0]=max(dp[v][0]+abs(l[v]−l[u]),dp[v][1]+abs(r[v]−l[u]))
d
p
[
u
]
[
1
]
=
m
a
x
(
d
p
[
v
]
[
1
]
+
a
b
s
(
l
[
v
]
−
r
[
u
]
)
,
d
p
[
v
]
[
1
]
+
a
b
s
(
r
[
v
]
−
r
[
u
]
)
)
dp[u][1] = max(dp[v][1] + abs(l[v] - r[u]), dp[v][1] + abs(r[v] - r[u]))
dp[u][1]=max(dp[v][1]+abs(l[v]−r[u]),dp[v][1]+abs(r[v]−r[u]))
树上计数
https://codeforces.ml/gym/103145/problem/C
每个节点会从儿子删除与不删除的两个状态转移过来,其中不删除的状态分为以儿子为根的子树结点数>1与<=1.
dp(u, 0): 节点删除的可能数目
dp(u, 1): 节点保留,以它为根的树大小>1(节点有儿子)
dp(u, 2): 节点保留,以它为根的树大小<=1(节点完全独立)
于是有
d
p
[
u
]
[
0
]
=
∏
v
(
d
p
[
v
]
[
0
]
+
d
p
[
v
]
[
1
]
)
dp[u][0] = \prod_{v} (dp[v][0] + dp[v][1])
dp[u][0]=v∏(dp[v][0]+dp[v][1])
如果删除这个节点,那么这个节点的可能排布是它的儿子要么删除,要么大小>1。
d
p
[
u
]
[
2
]
=
∏
v
d
p
[
v
]
[
0
]
dp[u][2] = \prod_{v} dp[v][0]
dp[u][2]=v∏dp[v][0]
d
p
[
u
]
[
1
]
=
∏
v
(
d
p
[
v
]
[
0
]
+
d
p
[
v
]
[
1
]
+
d
p
[
v
]
[
2
]
)
−
d
p
[
u
]
[
2
]
dp[u][1] = \prod_{v} (dp[v][0] + dp[v][1] + dp[v][2]) - dp[u][2]
dp[u][1]=v∏(dp[v][0]+dp[v][1]+dp[v][2])−dp[u][2]