【NOIP2017提高组正式赛】宝藏 题解

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

【NOIP2017提高组正式赛】宝藏 题解

题目大意

这道题目题目大意就是说,有一个图G=(V,E)G=(V,E)G=(V,E),求一个子图G′=(V,E′)G'=(V,E')G=(V,E),满足E′=V−1E'=V-1E=V1,也就是一棵树。
然后每一次一条边建出来的花费就是长度乘以这条边起点的深度加一。
求最小花费。

解题方法

关键词:状态压缩动态规划
fi,jf_{i,j}fi,j表示现在这棵树的深度为iii,整棵树的状态(用0/10/10/1表示)为jjj时,的最小花费。
画一个图好看一点。
在这里插入图片描述
那么显然可以从上一个转移过来。
kkk表示第iii层的结点。
则上一层的状态就是fi−1,k⊕jf_{i-1,k\oplus {j}}fi1,kj
画个图就显然了。
在这里插入图片描述
gp,qg_{p,q}gp,q表示从111到某层的上一层的状态为ppp,这一层的状态为qqq
那么转移就是
fi,j=min⁡k⊆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=kjminfi1,jk+gjk,k×(i1)
看上图就懂了。
然后考虑如何求ggg
首先qqq一定是ppp的补集的子集,也就是q⊆∁Spq\subseteq\complement_SpqSp(设全集(总状态)为SSS),原因很简单。
所以枚举qqq一定是p⊕Sp\oplus SpS的子集(子状态)。
在这里插入图片描述
然后我们把状态qqq中所有点都得算一遍,这样就得到了gp,qg_{p,q}gp,qgp,q⊕lowbit(q)g_{p,q\oplus lowbit(q)}gp,qlowbit(q)转移过来。
lowbit(i)lowbit(i)lowbit(i)表示二进制iii从末尾开始第一个111所构成的数。
也就是每一次选出一个二进制状态为lowbit(q)lowbit(q)lowbit(q)的点,算这个点的贡献。
这个点设为xxx,其实x=log⁡2lowbit(q)+1x=\log_{2}^{lowbit(q)}+1x=log2lowbit(q)+1,原因是我们点是从111开始计数的,而二进制状态是从000次方开始的。
而贡献就是状态ppp任意一个点到xxx的最小距离。
如图
在这里插入图片描述
所以可得
gp,q=gp,q⊕lowbit(j)+min⁡k∈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,qlowbit(j)+kpminck,x
ci,jc_{i,j}ci,jiiijjj的最小花费。

技巧

假若要枚举SSS的子集,可以用以下代码:

for(int i=S;i;i=(i-1)&S)

但是这样做iii是不断递减的,所以如果要从小到大枚举要存一个数组再反过来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值