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

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

题目大意

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

解题方法

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

技巧

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

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值