pku 3159 Candies 第一道Dijkstra+堆维护+差分约束系统的题目

2 篇文章 0 订阅
本题是一道典型的差分约束系统的题目,题目原意是这样子的:
    fq是幼稚园班上的老大,一天老师给小朋友们买了一堆的糖果,由fq来分发,在班上,fq和llw是死对头,两人势如水火,不能相容,因此fq希望自己分得的糖果数尽量多余llw,而对于其他小朋友而言,不患寡而患不均的意识甚是强烈,比如A小朋友强烈希望自己的糖果数不能少于B小朋友m个,即B-A<=m,A,B分别为A、B小朋友的分得的糖果数。如此,班上的小朋友存在若干这样的意识,题目要求你在满足其他小朋友的要求的情况下,使fq和llw分得的糖果数差别最大,即max(VN-V1),VN为fq获得的糖果数,V1为llw获得的糖果数。
    因此根据题意,可以列出如下的不等式:
    Vb1-Va1 <= a1b1
    Vb2-Va2 <= a1b2    (1)
      .....
    Vbm-Vam <= ambm               
    目标函数为:max(VN-V1)
    题目分析:(1)中的不等式正好可以构成最短路的三角不等式:du <= dv + w(v,w)(其中du、dv分为为u v点到起点的最短路经),因此可以利用最短路经来解求该不等式的解,同时利用最短路经得到的解能满足max{dn-d1},这一点在上一篇的评论中得到证明(因为图上的每个点的最短路经都是由其前驱节点(已计算出最短路径的节点)经过该点和前驱节点的边松弛得到的),因此最短路经得到的解X >= 满足该不等式的解。由于我们考虑的只是小朋友分得的糖果数的相对量,而不关心其绝对量,因此我们可以假定d1=0,即llw获得0个糖果数。因此d1==0,而dN达到最大值,固能满足{dN-d1}达到最大值。
    这道题与poj1716 Integer Intervals、poj1201 Intervals不同 还在于:该题不需要添加虚拟节点V0,因为V1可以从某种程度认为是虚拟节点,即起点。虚拟节点V0在差分约束系统中的作用是作为一个基准量,其他未知数以此基准量并根据不等式条件来得到解,这有点类似于水准高的定义,只是一个相对量。这里得声明下:虚拟节点的添加是为保证其他每个顶点均可从V0到达,从而在V0==0的情况下求解其他未知数,即只能以V0为起点,不能使用其他点作为起点,即其他点的未知量不为0。而本题,可以直接令V1=0,即以V1为起点,因为题目考虑的是VN-V1的相对量,因此,直接让V1=0,让V1成为起点,便可以。可以说,题目分析到这里,已经完成了1/3,后面的工作量还是比较大的。
    同时这道题还有一个难度在于数据量比较大,点有30000个,边有150000条,如果采用bellman_ford算法,需要的时间开销为30000*150000=4.5*e9,要在1s的时间算完比较困难。那么可以用dijkstra么?当然可以,因为图中的路径权都是正的,因此可以用dijkstra,但问题是dijkstra的时间复杂度为o(V*V+E)=9*e8,与bellman_ford算法其实相差无几,因此还需要优化。所以在使用dijkstra算法的同时,利用最小二分堆来实现最小优先队列的维护,其时间复杂度为o(ElgV)=1.5*lg(30000)*e5~近似等于=1.5*128*sqrt(2)*e5,比9*e8小了小了一个数量级,实践证明,程序运行时间约等于1s,刚好过,比较险。
    在《算法导论》中提到,利用斐波那契堆来实现优先队列,可以将运行时间提升到o(VlgV+E),目前还不知道斐波那契堆,有机会要摸一摸,体现一下告诉最短路经的快感。
    好,本题的题感写到这里,这道题做出来比较有成就感啊,虽然有部分思想源于网上,不过还是学到了不少。  


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值