Dijkstra 算法小结
By Wine93 2013.11
1 Dijkstra 算法相关介绍
算法阐述:Dijkstra是解决单源最短路径的算法,它可以在O(n^2)内计算出源点(s)到图中任何顶点的最短路,但是该算法不能处理存在负权边的图(证明中会给出)。
Dijkstra一般有2种实现,一种采用邻接矩阵,复杂度为O(n^2),这种实现适用于稠密图 (边多点少),还有一种是采用临接表+heap(可用优先队列代替)实现,实现的复杂度为( m*log(n) ) (m为边数,n为顶点数),该实现适用于稀疏图(边少点多),各有各的优缺,视实际情况选择.
算法简单证明:Dijkstra有2张表(OPEN,CLOSE),我们可以认为一个表存储已经已经计算出最短路径的顶点(假设U),而另一个则存储没有计算出最短路径的顶点(假设V)。Dijkstra每次都取出具有最短路径的顶点(假设NOW),视其就是该顶点的最短路.因为在当前U表中全部扩展的顶点中,NOW顶点是路径最短的顶点,也就是说,其他当前全部可以到达的顶点中,只有大于或等于NOW顶点,如果 通过这些顶点再到达NOW顶点,势必会比现在NOW顶点的路径长,因为原来就大于等于NOW顶点了, 所以NOW顶点路径长度就是源点到该顶点的最短路径.但是如果存在负权边,则会出现通过其他顶点到达NOW顶点的路径长度小于当前NOW顶点的路径长度,这就是为什么Dijkstra不能处理负权边了(请读者看下面例图,模拟下Dijkstra的执行过程)
2.Dijkstra的相关应用举例
一.基础题
POJ 1511 Invitation Cards
POJ 3013 Big Christmas Tre(重点在于思维的转换)
二.变形题
POJ 1797 Heavy Transportation
POJ 2253 Frogger
将这2题放在一起讲(2题都可用2分解),我们可以利用Dijkstra特殊的结构解决一类问题----单调路径(况且这么叫),所谓单调路径,即为对于任何一条路径, 我们所求的值只会成单调变化
拿POJ1797来说,每经过一条路径,weight的值只会减少(甚至不变),不会增加,看下图(边权值表示 weight,红色顶点为起点,绿色为终点,顶点下数字表示从起始点到达该顶点的weight值)
我们可以发现weight呈现非递增,而我们要求的则是weight的最大值,也就是说我们求的和它的趋势相反都可用Dijkstra来题解(请看下图),这跟Dijkstra可用heap优化是异曲同工(可以认真理解证明)
如果所求值和趋势为同一走向则不能用Dijkstra求解(如最长路)
三.好题
POJ 3463 Sightseeing
3.个人心得
Dijkstra的变形和应用非常多,需要一定的时间和题量积累,但是只要能深入理解Dijkstra的贪心 策略以及他在单调路径上(况且这么叫)的作用,很多问题都会迎刃而解