题目大意
从前有棵树。找出kkk个点A1,A2,…,AkA_1,A_2,\dots,A_kA1,A2,…,Ak,使得∑i=1k−1dist(Ai,Ai+1)\sum\limits_{i=1}^{k-1}dist(A_i,A_{i+1})i=1∑k−1dist(Ai,Ai+1)最小。
1⩽N⩽30001\leqslant N\leqslant 30001⩽N⩽3000。
思路
题目要求的是从点A1A_1A1开始,依次经过A2,A3,…A_2,A_3,\dotsA2,A3,…,最后到达AkA_kAk走过的最短路程。
首先,这kkk个点中任意两点之间一定不会有这kkk个点以外的点,否则把这个点纳入kkk个点内,得到的方案更优。于是这kkk个点构成了一棵大小为kkk的树,并且是原树的一部分。
其次,A1A_1A1到AkA_kAk这条路径上的边被经过一次,其余的边都被经过两次。可以通过画图验证。
根据树形背包的套路,容易定出状态f[u][i]f[u][i]f[u][i],表示从以uuu为根的子树中选出包含uuu的iii个点对答案的贡献,然后把点uuu自身以外的i−1i-1i−1个点分配给每个儿子vvv。但是边(u,v)(u,v)(u,v)被经过的次数无法确定。
在状态后面添加一维jjj,表示选择的iii个点中有jjj个点是A1A_1A1到AkA_kAk这条路径的端点(起点A1A_1A1或终点AkA_kAk)。jjj的范围是[0,2][0,2][0,2]。下面分情况讨论。
- uuu已讨论的部分子树和vvv的子树中都没有路径的端点,那么这条路径一定没有经过边(u,v)(u,v)(u,v)。这条边被经过了两次。
- uuu已讨论的部分子树中没有路径的端点,而vvv的子树中有一个,那么这条路径从vvv的子树内出发,经过边(u,v)(u,v)(u,v),走到了已讨论的子树外的部分。这条边被经过了一次。
- uuu已讨论的部分子树中有一个路径的端点,而vvv的子树中没有,那么这条路径从uuu已讨论的子树内出发,没有进入vvv的子树内,说明路径没有经过边(u,v)(u,v)(u,v)。这条边被经过了两次。
- uuu已讨论的部分子树中没有路径的端点,而vvv的子树中有两个,那么这条路径被包含在vvv的子树内,没有经过边(u,v)(u,v)(u,v)。这条边被经过了两次。
- uuu已讨论的部分子树和vvv的子树各有一个端点,那么这条路径一定经过边(u,v)(u,v)(u,v)。这条边被经过了一次。
- uuu已讨论的部分子树中有两个路径的端点,而vvv的子树中没有,那么这条路径被包含在uuu已讨论的子树内,没有经过边(u,v)(u,v)(u,v)。这条边被经过了两次。
很好看的状态转移方程:
f[u][i+j][0]=min{f[u][i][0]+f[v][j][0]+len(u,v)⋅2}f[u][i+j][1]=min{f[u][i][0]+f[v][j][1]+len(u,v)f[u][i][1]+f[v][j][0]+len(u,v)⋅2f[u][i+j][2]=min{f[u][i][0]+f[v][j][2]+len(u,v)⋅2f[u][i][1]+f[v][j][1]+len(u,v)f[u][i][2]+f[v][j][0]+len(u,v)⋅2\begin{aligned} f[u][i+j][0]&=\min\{f[u][i][0]+f[v][j][0]+len(u,v)\cdot 2\}\\ f[u][i+j][1]&=\min\begin{cases} f[u][i][0]+f[v][j][1]+len(u,v)\\ f[u][i][1]+f[v][j][0]+len(u,v)\cdot 2 \end{cases}\\ f[u][i+j][2]&=\min\begin{cases} f[u][i][0]+f[v][j][2]+len(u,v)\cdot 2\\ f[u][i][1]+f[v][j][1]+len(u,v)\\ f[u][i][2]+f[v][j][0]+len(u,v)\cdot 2 \end{cases} \end{aligned}f[u][i+j][0]f[u][i+j][1]f[u][i+j][2]=min{f[u][i][0]+f[v][j][0]+len(u,v)⋅2}=min{f[u][i][0]+f[v][j][1]+len(u,v)f[u][i][1]+f[v][j][0]+len(u,v)⋅2=min⎩⎪⎨⎪⎧f[u][i][0]+f[v][j][2]+len(u,v)⋅2f[u][i][1]+f[v][j][1]+len(u,v)f[u][i][2]+f[v][j][0]+len(u,v)⋅2