Loading

关于树上背包复杂度的证明

众所周知,树上背包如果上下界都卡紧了复杂度会是 \(O(nm)\),下面来进行这一点的证明。

以下设节点总数为 \(n\),背包容量最大是 \(m\)

合并两个泛化背包的复杂度为 \(O(s_1s_2)\),其中 \(s_1\) 是第一个泛化背包的容量,\(s_2\) 是第二个背包的容量,但这个复杂度是在背包容量不设上限的情况下。

而在树上背包中,容量是有上限的。做树上背包的过程,实际上就是把 \(n\) 个节点合并到一个背包的过程,显然,合并的总次数是 \(O(n)\) 的。

合并过程的时间复杂度显然只跟 \(s_1,s_2,m\) 有关系,其中 \(s_1,s_2\le m\),代表的含义是两个背包分别的容量。不难发现,合并这两个背包的复杂度应该是 \(O(\min(s_1+s_2,m)\times \min(s_1,s_2))\),之所以有这两个式子是因为我们首先枚举最终的背包的容量是多大,然后枚举较小背包放多少个。

在实际操作中,我们不需要比较哪个背包较小,我们只需要给下界设置一个合适的值,设 \(i\) 为枚举的最终背包容量,\(j\) 是当前背包放多少个,只需要设置一个下界让 \(i-j\) 满足不超过另一个背包的值即可。不难发现这和直接枚举较小背包容量是等价的。

我们对 \(s_1\)\(s_2\) 的大小进行分类讨论。

\(s_1=m,s_2=m\) 容易发现这样的合并不会超过 \(\frac{n}{m}\) 次,这是因为两边背包容量都等于 \(m\),说明有很多超过 \(m\) 个点被考虑进的背包内,因为我们的最终目标是把所有点合并成一个背包,而合并超过 \(m\) 个点的背包不超过 \(\frac{n}{m}\) 个,原命题得证。由此,这里的复杂度是 \(O(nm)\) 的。

\(s_1<m,s_2<m\)\(s_1+s_2\ge m\) 这种情况下的合并次数不会超过 \(\frac{n}{m}\),因为这相当于把大小小于 \(m\) 的子树全部合并,最坏情况是合并到不存在大小小于 \(m\) 的子树,由大小大于等于 \(m\) 的子树个数不会超过 \(\frac{n}{m}\) 可以知道合并次数不会超过 \(\frac{n}{m}\) 由此可知复杂度不会超过 \(O(nm)\)

\(s_1<m,s_2<m\)\(s_1+s_2< m\) 我们考虑一下 \(m\) 个点合并成为一棵大小为 \(m\) 的树,总的复杂度应该为 \(m^2\),总共这样的树的个数不会超过 \(\frac{n}{m}\) 个,故最终的复杂度也应该为 \(O(nm)\)。由这段证明我们也可以得到所谓背包大小为 \(m\),实际上是一个限制,其标明整个树形背包的复杂度不会超过 \(O(n^2)\),当然大多数情况下我们认为 \(m<n\)

由此可以得出,树上背包的复杂度为 \(O(nm)\)

posted @ 2022-01-03 07:17  hyl天梦  阅读(1289)  评论(1编辑  收藏  举报