动态DP

例题【洛谷P4719

给定一棵树,节点$x$的权值为$w[x]$,维护以下两个操作:

1. 修改一个节点的权值;

2. 询问当前的最大独立集的权值。

解:

假设没有修改操作,则是一个典型的树形动态规划。设$f[x][0]$表示未选择节点$x$的情况下的最大权值,$f[x][1]$表示选择了节点$x$的情况下的最大权值,则

$$ f[x][0] = sum_{y in ext{son}(x)} max{f[y][0], f[y][1]}, $$

$$ f[x][1] = w[x] + sum_{y in ext{son}(x)} f[y][0]. $$

特别地,若$x$是叶子节点,则$f[x][0] = 0, f[x][1] = w[x]$.

将这棵树树链剖分后,令$ ext{heavy}(x)$表示节点$x$的重儿子,$ ext{light}(x)$表示节点$x$的轻儿子的集合。若$x$非叶节点,则

$$ f[x][0] = max{ f[ ext{heavy}(x)][0], f[ ext{heavy}(x)][1] } + g[x][0], $$

$$ f[x][1] = f[ ext{heavy}(x)][0] + g[x][1], $$

其中

$$ g[x][0] = sum_{y in ext{lignt}(x)} max{f[y][0], f[y][1]}, $$

$$ g[x][1] = w[x]+ sum_{y in ext{lignt}(x)} f[y][0]. $$

我们引入广义矩阵乘法,其加法为$max$,其乘法为$+$,对于两个矩阵$A$和$B$,其积$C = A*B$定义为

$$C_{ij} = max_k {A_{ik}+B_{kj}}.$$

我们可以把节点$x$与其重儿子$ ext{heavy}(x)$的动态规划递推式写作

$$ egin{bmatrix} f[x][0] \ f[x][1] end{bmatrix} = egin{bmatrix} g[x][0] & g[x][0] \ g[x][1] & -infty end{bmatrix} * egin{bmatrix} f[ ext{heavy}(x)][0] \ f[ ext{heavy}(x)][1] end{bmatrix}. $$

我们记

$$ M[x] = egin{bmatrix} g[x][0] & g[x][0] \ g[x][1] & -infty end{bmatrix}. $$

设$x = x_0 o x_1 o dots o x_k$是以$x$出发的重链,则以$x$为根的子树的最大独立集的权值可通过下式给出:

$$ egin{bmatrix} f[x][0] \ f[x][1] end{bmatrix} = M[x_0] * M[x_1] * dots * M[x_{k-1}] * egin{bmatrix} 0 \ w[x_k] end{bmatrix}. $$

这个式子可以写得更优美一点:

$$ egin{bmatrix} f[x][0] \ f[x][1] end{bmatrix} = M[x_0] * M[x_1] * dots * M[x_k] * egin{bmatrix} 0 \ 0 end{bmatrix}. $$

对于修改节点$x$的权值,我们只需要修改 $g[x][0], g[x][1]$ 以及节点$x$到根的路径中与其他重链交汇的那些节点,最多$O(log n)$个。

故树链剖分能在$O(log^2n)$的复杂度内维护单次操作。

P.S. 可以利用动态树(Link-Cut Tree)把复杂度进一步降为单次操作$O(log n)$。甚至还可以维护其他操作,如修改一个节点的父节点,以及询问某个子树的最大独立集等。

然而这种神奇的动态DP居然在NOIP2018的Day2第三题【保卫王国】出现了。这也太超纲了吧,NOI2018的Day2第三题还差不多。

不一样的是,【保卫王国】求的是最小点集覆盖。但二分图中,最小点集覆盖 = 权值之和 - 最大独立集。因此两个问题的求解是等价的。

动态DP例题:

洛谷P4719

NOIP2018. 保卫王国

CEOI2019. Dynamic Diameter

原文地址:https://www.cnblogs.com/TinyWong/p/11227272.html