2022 International Collegiate Programming Contest, Jinan Site C. DFS Order 2(树形dp+回滚背包)

本文介绍了如何利用回退背包和递推思想解决一个关于n个点的树问题,计算每个点在DFS序中的特定位置被访问的方案数。关键步骤包括计算子树贡献、构建f数组、生成g数组以及合并dp数组。
题目

n(n<=500)个点的树,是一棵以1为根的有根树,

你需要输出一个n*n的矩阵,

(i,j)表示点i在dfs序中是第j个被访问的节点的方案数

答案对998244353取模

思路来源

官方题解+严格鸽博客

2022 ICPC 济南站 C (回退背包) - 知乎

题解

官方题解是上面这样写的

感觉参考了这个方法的一部分,也参考了严格鸽方法的一部分,

结合二者,也用了一下自己统计的方法

1. 求总方案数

h[i]表示只考虑i的子树里的点时,dfs序的方案数

自然是子树中每个点直连儿子个数的乘积,

也就是,先令h[u]=1,对于u的每个直连儿子来说,h[u]*=h[v],

再h[u]*=m!,其中m为u的直连儿子个数

2. 求只考虑u这棵子树时,把u的若干个儿子v看成(1,sz[v]),

第一维表示是一个直连儿子,第二维表示这个儿子的子树大小

因为访问一个直连儿子,紧接着就要访问这个儿子内子树的所有点

考虑怎么算出,dfs序中,u到v的距离恰为k的方案数

g[k+1]表示dfs序中u到v的距离恰为k+1的方案数

此时仅考虑u的子树中的点,由于每搜到u都需要重做一遍,所以第一维可以滚动掉

则需要u到v中放入k个点,这些点是由u的i个直连儿子(不包括v)贡献的,

i个儿子的子树大小总共为k

所以,计f[i][j]表示考虑u的子树,选了i个儿子,这i个儿子的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值