关于树形背包时间复杂度为什么会比想象中少一阶

Upd 2024年12月18日

将树拍到 DFS 序上,合并两个子树时认为复杂度是左子树 DFS 序最大的 \(V\) 个点和右子树 DFS 序最小的 \(V\) 个点个数相乘,则整个序列中只有下标差 \(\le 2V-1\) 的点对有贡献,所以是 \(O(nV)\)

Upd 2022年10月3日

对于树上的任意一点 \(x\),我们设其贡献的时间复杂度为 \(T(x)\)

\(x\) 的儿子大小分别是 \(p_1,\dots,p_c\),设 \(x\) 的大小为 \(p_0=1+\sum_{i=1}^cp_i\),则

\[\begin{aligned} T(x)=&1 \\&+p_1 \\&+p_2(1+p_1) \\&+p_3(1+p_1+p_2) \\&+\dots \\&+p_c(1+p_1+\dots+p_{c-1}) \\=&1+\frac{(1+\sum_{i=1}^cp_i)^2-1-\sum_{i=1}^cp_i^2}{2} \\=&\frac{1}{2} (1+p_0^2-\sum_{i=1}^cp_i^2)\end{aligned} \]

发现不论以什么顺序合并儿子复杂度都是相同的。

总复杂度

\[\sum_{i=1}^n T(i)=\frac{1}{2}(n+n^2) \]

相当于把 \(-p_i^2\) 这部分负贡献给这个儿子,抵消后只剩根节点 \(\text{size}\) 的平方了。

远古

下面的东西太 naive 了,差不多别看了,谢谢。

思路来自 Konata,有删改及本作者的想法

如果正常想,每个节点都要进行 \(O(n^2)\) 的背包,则时间复杂度为 \(O(n^3)\),其实不然。

假设 \(n\) 个节点的树形背包的时间复杂度为 \(f(n)\)

那么假设根节点下面的子树大小分别为 \(p_1,p_2,\dots,p_k\),子树大小 \(p_i\) 对应的子树根节点下面的子树大小分别为 \(g_{i,1},g_{i,2},\dots,g_{i,s_i}\)

\[\begin{aligned}f(n) &=\sum\limits^k_{i=1}f(p_i)+\sum\limits^k_{i=2}\left(p_i\times\sum\limits^{i-1}_{j=1}p_j\right) \\ & = \sum\limits^k_{i=1}f(p_i)+\sum\limits_{1\leqslant i<j\leqslant k}p_i\times p_j \\ & = \sum\limits^k_{i=1}f(p_i)+\dfrac{\left(\sum\limits^k_{i=1}p_i\right)^2-\sum\limits^k_{i=1}p_i^2}{2} \\ & = \dfrac{1}{2}(n-1)^2+\sum\limits^k_{i=1}f(p_i)-\dfrac{1}{2}\sum\limits^k_{i=1}p_i^2 \\ & \leqslant \dfrac{1}{2}n^2+\sum\limits^k_{i=1}(f(p_i)-\dfrac{1}{2}p_i^2) \\ & = \dfrac{1}{2}n^2+\sum\limits^k_{i=1}(\dfrac{1}{2}(p_i-1)^2+\sum\limits^{s_i}_{j=1}(f(g_{i,j})-\dfrac{1}{2}g_{i,j}^2)-\dfrac{1}{2}p_i^2) \\ & \leqslant \dfrac{1}{2}n^2+\sum\limits^k_{i=1}\sum\limits^{s_i}_{j=1}(f(g_{i,j})-\dfrac{1}{2}g_{i,j}^2) \\ & \leqslant \dfrac{1}{2}n^2+\sum\sum\dots\sum(f(\dots)-\dfrac{1}{2}(\dots)^2) \\ & \leqslant \dots \\ & \leqslant \dfrac{1}{2}n^2 \\ & =O(n^2) \end{aligned}\]

特殊得,如果背包的容量上限为 \(V\),则总时间复杂度为 \(O(nV)\)

posted @ 2021-11-07 17:21  ShaoJia  阅读(295)  评论(0)    收藏  举报