单元最短路径——Dijkstra

来源:互联网 发布:项目管理 java开源 编辑:程序博客网 时间:2024/05/29 00:33

1.算法思想

   输入:带权有向图(权重均为非负值)G(V,E)、权重函数ω(所有边的权重都为非负值)、源点s

  过程:维持一个集合S,从源点s到S的最短路径都已经寻找到,最短路径权重保存在每个结点的d值当中。每一次从V-S集合中选出d值最小的结点u,将u加入到S中,并对从u发出的边进行松弛。

  输出:源点s到每一个结点的最短路径。


2.伪代码:

 DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S ← Ø
3 Q ← V[G]//INSERT,O(1)
4 while Q ≠ Ø
5    u ← EXTRACT-MIN(Q)
6    S ← S ∪{u}
7    for each vertex v ∈ Adj[u]
8         RELAX(u, v, w)

3.正确性

  证明:按照Dijkstra算法,在算法结束时,对于所有结点u,u.d=δ(s,u)

     要证明以上结论,只需证明,在算法的while开始前,对于S中的每一个结点S,都有u.d=δ(s,u)

     初始化:S = Ø时,以上结论成立

     保持:(反证)假设在u是第一个加入到S时使得以上等式不成立的结点。

      由于s是第一个加入到S中的结点,而s.d=δ(s,s)=0,故u ≠s。则在u加入到S里面时有 S≠Ø。,此时一定存在一条从s到u的路径,否则u.d=δ(s,u)=∞,不符合假设。因为至少存在一条从s到u的路径,所以也存在一条从s到u的最短路径p。在将u加入到集合S之前,路径p连接的是集合S中的一个结点(s)以及V-S中的一个结点(u),

    考虑路径p上第一个满足y∈V-S的结点y,设x∈S为结点y在路径p上的前驱则可以将p分解为s~x-->y~u(s~x,y~u可能不包含任何边)

(忘记画方向了。。。)

    则将u加入S时,y.d=δ(s,y)。(因为x∈S,x.d=δ(s,x)),此时(x,y)将贝松驰,根据收敛性质得出结论)

    此时,因为y是最短路径p上的位于u前面的一个结点,而所有边权重都为非负值,所有δ(s,y)≤δ(s,u)

    故  y.d=δ(s,y)≤δ(s,u)≤u.d

   但是,在算法第5行选择u时,结点u,y都在V-S中,u.d<=y.d,

   故   y.d=δ(s,y)=δ(s,u)=u.d  与假设矛盾

    终止:算法终止时,Q=Ø,而算法开始时Q=V-S,故算法结束时,S=V,即对于所有结点u.d=δ(s,u)


4.时间复杂度

   每次选d值最小O(VlgV),选出d值最小结点u之后进行松弛总共O(ElgV)

  总时间复杂度 O((V+E)lgV)



 

0 0