【NOIP2017提高组正式赛】宝藏 题解
题目大意
这道题目题目大意就是说,有一个图G=(V,E)G=(V,E)G=(V,E),求一个子图G′=(V,E′)G'=(V,E')G′=(V,E′),满足E′=V−1E'=V-1E′=V−1,也就是一棵树。
然后每一次一条边建出来的花费就是长度乘以这条边起点的深度加一。
求最小花费。
解题方法
关键词:状态压缩动态规划
设fi,jf_{i,j}fi,j表示现在这棵树的深度为iii,整棵树的状态(用0/10/10/1表示)为jjj时,的最小花费。
画一个图好看一点。

那么显然可以从上一个转移过来。
设kkk表示第iii层的结点。
则上一层的状态就是fi−1,k⊕jf_{i-1,k\oplus {j}}fi−1,k⊕j。
画个图就显然了。

设gp,qg_{p,q}gp,q表示从111到某层的上一层的状态为ppp,这一层的状态为qqq。
那么转移就是
fi,j=mink⊆jfi−1,j⊕k+gj⊕k,k×(i−1)\begin{aligned}f_{i,j}=\min_{k\subseteq j}f_{i-1,j\oplus k}+g_{j\oplus k,k}\times(i-1)\end{aligned}fi,j=k⊆jminfi−1,j⊕k+gj⊕k,k×(i−1)
看上图就懂了。
然后考虑如何求ggg。
首先qqq一定是ppp的补集的子集,也就是q⊆∁Spq\subseteq\complement_Spq⊆∁Sp(设全集(总状态)为SSS),原因很简单。
所以枚举qqq一定是p⊕Sp\oplus Sp⊕S的子集(子状态)。

然后我们把状态qqq中所有点都得算一遍,这样就得到了gp,qg_{p,q}gp,q从gp,q⊕lowbit(q)g_{p,q\oplus lowbit(q)}gp,q⊕lowbit(q)转移过来。
lowbit(i)lowbit(i)lowbit(i)表示二进制iii从末尾开始第一个111所构成的数。
也就是每一次选出一个二进制状态为lowbit(q)lowbit(q)lowbit(q)的点,算这个点的贡献。
这个点设为xxx,其实x=log2lowbit(q)+1x=\log_{2}^{lowbit(q)}+1x=log2lowbit(q)+1,原因是我们点是从111开始计数的,而二进制状态是从000次方开始的。
而贡献就是状态ppp任意一个点到xxx的最小距离。
如图

所以可得
gp,q=gp,q⊕lowbit(j)+mink∈pck,x\begin{aligned}g_{p,q}=g_{p,q\oplus lowbit(j)}+\min_{k\in p}{c_{k,x}}\end{aligned}gp,q=gp,q⊕lowbit(j)+k∈pminck,x
ci,jc_{i,j}ci,j为iii到jjj的最小花费。
技巧
假若要枚举SSS的子集,可以用以下代码:
for(int i=S;i;i=(i-1)&S)
但是这样做iii是不断递减的,所以如果要从小到大枚举要存一个数组再反过来。

该博客介绍了如何使用状态压缩动态规划解决图论问题,特别是寻找最小成本的树形子图。通过深度和状态转移方程,解释了如何计算每个节点的最小花费,并给出了关键代码片段。文章强调了枚举子集的技巧,并提供了清晰的转移逻辑。
1901

被折叠的 条评论
为什么被折叠?



