给定一个带权有向图 G = ( V , E ) G = (V , E) G=(V,E),其中每条边的权是非负实数,给定 V V V中的一个顶点,称为源
计算从源到所有其他各顶点的最短路径长度
Dijkstra算法
Dijkstra算法是解单源最短路径问题的一个贪心算法
其基本思想是,设置顶点集合 S S S,并不断地做贪心选择来扩充这个集合,一个顶点属于集合 S S S当且仅当从源到该顶点的最短路径长度已知
初始时, S S S中仅含有源,设 u u u是 G G G的某一个顶点,把从源到 u u u且中间只经过 S S S中顶点的路称为从源到 u u u的特殊路径,并用数组 d i s t dist dist记录当前每个顶点所对应的最短特殊路径长度,用数组 p a r e n t [ i ] parent[i] parent[i]记录从源到顶点 i i i的最短路径上 i i i的前一个顶点
Dijkstra算法每次从 V − S V - S V−S中取出具有最短特殊路长度的顶点 u u u,将 u u u添加到 S S S中,同时对列表 d i s t dist dist和 p a r e n t parent parent做必要的修改,当 d i s t [ u ] + g r a p h [ u ] [ i ] < d i s t [ i ] dist[u] + graph[u][i] < dist[i] dist[u]+graph[u][i]<dist[i]时,置 d i s t [ i ] = d i s t [ u ] + g r a p h [ u ] [ i ] dist[i] = dist[u] + graph[u][i] dist[i]=dist[u]+graph[u][i],置 p a r e n t [ i ] = u parent[i] = u parent[i]=u
一旦 S S S包含了所有 V V V中顶点, d i s t dist dist就记录了从源到所有其他顶点之间的最短路径长度
Dijkstra算法的正确性
贪心选择性质
Dijkstra算法所做的贪心选择是从 V − S V - S V−S中选择具有最短特殊路径的顶点 u u u,从而确定从源到 u u u的最短路径长度 d i s t [ u ] dist[u] dist[u],从源到 u u u没有更短的其他路径
事实上,如果存在一条从源到 u u u且长度比 d i s t [ u ] dist[u] dist[u]更短的路,设这条路初次走出 S S S之外到达的顶点为 x ∈ V − S x \in V - S x∈V−S,然后徘徊于 S S S内外若干次,最后离开 S S S到达 u u u
在这条路径上,分别记 d ( v , x ) d(v , x) d(v,x)、 d ( x , u ) d(x , u) d(x,u)和 d ( v , u ) d(v , u) d(v,u)为顶点 v v v到顶点 x x x、顶点 x x x到顶点 u u u和顶点 v v v到顶点 u u u的路长,那么 d i s t [ x ] ≤ d ( v , x ) dist[x] \leq d(v , x) dist[x]≤d(v,x), d ( v , x ) + d ( x , u ) = d ( v , u ) < d i s t [ u ] d(v , x) + d(x , u) = d(v , u) < dist[u] d(v,x)+d(x,u)=d(v,u)<dist[u],利用边权的非负性,可知 d ( x , u ) ≥ 0 d(x , u) \geq 0 d(x,u)≥0,从而推得 d i s t [ x ] < d i s t [ u ] dist[x] < dist[u] dist[x]<dist[u],此为矛盾
这就证明了 d i s t [ u ] dist[u] dist[u]是从源到顶点 u u u的最短路径长度
最优子结构性质
将添加 u u u之前的 S S S称为 S ′ S^{'} S′
当添加了 u u u后,可能出现一条到顶点 i i i的新的特殊路
如果这条新特殊路是经过 S ′ S^{'} S′到达顶点 u u u,然后从 u u u经一条边直接到达顶点 i i i,则这种路的最短的长度是 d i s t [ u ] + c [ u ] [ i ] dist[u] + c[u][i] dist[u]+c[u][i],此时,如果 d i s t [ u ] + c [ u ] [ i ] < d i s t [ i ] dist[u] + c[u][i] < dist[i] dist[u]+c[u][i]<dist[i],则算法中用 d i s t [ u ] + c [ u ] [ i ] dist[u] + c[u][i] dist[u]+c[u][i]作为 d i s t [ i ] dist[i] dist[i]的新值
如果这条新特殊路经过 S ′ S^{'} S′到达 u u u后,不是从 u u u经一条边直接到达 i i i,而是回到 S ′ S^{'} S′中某个顶点 x x x,最后才到达顶点 i i i,那么由于 x x x在 S ′ S^{'} S′中,因此 x x x比 u u u先加入 S S S,故从源到 x x x的路的长度比从源到 u u u,再从 u u u到 x x x的路的长度小,于是当前 d i s t [ i ] dist[i] dist[i]的值小于这条新特殊路的长度,因此,在算法中不必考虑这种路
由此可知,不论算法中 d i s t [ u ] dist[u] dist[u]的值是否有变化,它总是关于当前顶点集 S S S到顶点 u u u的最短特殊路径长度