PKU 1062 单源最短路径

Dijkstra算法:有向图G=(V,E)

1、把源点v0放入到集合S中,计数器c=0。每个结点一个结构数据d(a,b), a表示到v0的最短路径长,b表示a的前趋节点。初始化v0为d(0,-)并且除v0外的所有节点为d(INF,-)。这里面INF表示无穷大。

 

2、通过遍历集合S中所有节点v,来更新非集合S中所有节点u.

     更新条件为 d[u].first = min{du[u].first, d[v].first + wt(v,u)},其中d[u].first表示u节点数据的每一个元素,即u节点到源点最短路径长。wt(v,u)表示节点v到节点u的路径长。除了更新最短路径长,而且更新前趋节点。

     此时,所有非集合S中节点数据更新完毕。如果

     a、非集合S中所有节点数据d为(INF,-),此时的图为所求,表示这些非集合S中节点由源点不可达。

     b、否则,从这个节点中选择d.first最少的节点加入到集合S中,计数器加一

 

3、当计数器c=n-1时,此时图为所求,并且所有节点可达。

优化:第2步中更新所有非集合S中节点时,不需要遍历所有集合S中节点,只需要判断上一次迭代新加入的节点即可。

 

 

题意:探险家如何用最少的金币获得酋长所要的物品。每个节点附有等级、金币数的值。如果A物品可以用B物品和C个金币代替,那么由A到B的边权值为C。

分析:每个物品为一个节点。酋长所要物品为源节点。求源节点到其它节点的最短路径。结果是到所有节点最短路径加上物品价值和的最小值。说几点需要注意的问题:

1、等级的处理:题中规定等级超过m的物品不可以交换,包括间接交换。比如a、b、c等级为1、2、3,如果等级限制为1的话,不可以通过a换b,b再换c这种方式,因为a与c的等级超过1。所以如果单次dijkstra求最短路径时,我们很难确定是否加入非集合S的的节点,因为不清楚当前节点是否满足等级要求,或者是否对未来要加入节点等级造成影响。所以目前采用的是枚举范围的方法,有一个事情我们是确定的,即初始节点的等级一定是在等级范围里的。所以我们枚举(lev[s]-m, lev[s])到(lev[s],lev[s]+m)等级范围。在处理最短路径新加入节点时要求节点等级大于等于最低等级,小于等于最高等级。

2、有向图问题:A物品可以用B物品和C个金币代替,表示A到B的边权为C,但是并不说明B到A也有一条权为C的边,注意!

3、初始化问题:既然要多次运行dijkstra,那么最小路径长度一定要初始化。我前几次WA就是错在这里,因为每次dijstra数据具有相似性,所以好多数据都检查不出来。

4、表示无穷大的INF=(1>>30)-1足够,邻接矩阵用int也足够,并不像DISCUSS中有人提到的要开INF=(1>>31)-1.

 

 

 

源码如下:

 

  

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值