返回分类:全部文章 >> 基础知识
返回上级:编程基础 - 图 (Graph)
本文将介绍最短路径的基础知识,并用C++实现迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyed)。
在查看本文之前,需要一些数据结构和程序语言的基础。
尤其是“矩阵”、“矩阵的压缩(matrix)”、“图(graph)”等的知识。
最短路径问题是找到一个顶点到另一个顶点之间权值之和最小的路径。
一个顶点称为源点
另一个顶点称为终点
其图是有向带权图。
迪杰斯特拉算法 (Dijkstra) 适用于:
(1)源点只有一个;
(2)权值必须都是大于等于零。
Dijkstra算法意指按照路径长度的递增次序,逐步的产生最短路径。
(1)首先、求出长度最短的一条最短路径;
(2)其次,参照它求出长度次短的一条最短路径;
(3)最后,重复步骤(2)直到求出所有最短路径。
假设原图,起始点A:
10 50 30 90 10 20 70 99 A B C D E F其从A开始到达各个点的权值,取最小值就是路径:
到达点\经过边数123BAB(10)CABC(60), ADC(50)DAD(30)EAE(90)ADE(100)ABCE(70), ADCE(60)F其算法描述:
假设 n 个顶点, e 条边的图,求得最短路径的集合为 P, 顶点为 { v0, v1, … , vn }, 权值和的数组为 cost[n]。 (1)初始化: P = { v0 } , cost[vadj] = Edge[v0][vadj] ;(adj为邻接顶点)(2)获取最短路径,并添加顶点: cost[vmin] = min(cost) , P = { v0, vmin } ;(3)更新路径长度与路径:cost[vminadj] = min(cost[vminadj], cost[vmin] + Edge[vmin][vminadj]) ;(4)重复步骤(2)和(3):直到所有顶点检测完成。其 n 个顶点的图,时间复杂度 O(n2) 。
弗洛伊德算法 (Floyed) 相比较于 迪杰斯特拉算法 (Dijkstra) 它:
(1)可以有多个源点;
(2)权值可以是负数,但负数权值不能组成回路。
(3)复杂度更高。
对有 n n n 个顶点, e e e 条边,权值为 ( e i j ) n × n (e_{ij})_{n \times n} (eij)n×n 的图:
(1)它是通过一个 n n n 阶方阵求出每两点间的最短路径,即
A = { A ( 0 ) , A ( 1 ) , ⋯   , A ( n ) } A = \{ A^{(0)}, A^{(1)}, \cdots, A^{(n)} \} A={A(0),A(1),⋯,A(n)}
其中: A ( 0 ) = ( a i j ) n × n ( 0 ) , ( a i j ) ( 0 ) = e i j A ( k ) = ( a i j ) n × n ( k ) , ( a i j ) ( k ) = min { ( a i j ) ( k − 1 ) , ( a i k ) ( k − 1 ) + ( a k j ) ( k − 1 ) } , k ∈ [ 1 , n ] \begin{aligned} A^{(0)} &=(a_{ij})^{(0)}_{n \times n}, &(a_{ij})^{(0)} &=e_{ij} \\ A^{(k)} &=(a_{ij})^{(k)}_{n \times n}, &(a_{ij})^{(k)} &= \min \{(a_{ij})^{(k-1)}, (a_{ik})^{(k-1)} + (a_{kj})^{(k-1)}\}, & k \in [1, n] \end{aligned} A(0)A(k)=(aij)n×n(0),=(aij)n×n(k),(aij)(0)(aij)(k)=eij=min{(aij)(k−1),(aik)(k−1)+(akj)(k−1)},k∈[1,n]
(2) ( a i j ) ( 0 ) (a_{ij})^{(0)} (aij)(0) 是从顶点 v i v_i vi 到 v j v_j vj ,以 v 0 v_0 v0 为中介的最短路径长度;
(3) ( a i j ) ( k ) (a_{ij})^{(k)} (aij)(k) 是从顶点 v i v_i vi 到 v j v_j vj ,以 v 0 , v 2 , ⋯   , v k v_0, v_2, \cdots, v_k v0,v2,⋯,vk 为中介的最短路径长度;
(4) ( a i j ) ( n ) (a_{ij})^{(n)} (aij)(n) 是从顶点 v i v_i vi 到 v j v_j vj 的最短路径长度。
(5)在计算最短路径长度的同时,更新路径:
P a t h = { P ( 0 ) , P ( 1 ) , ⋯   , P ( n ) } Path = \{ P^{(0)}, P^{(1)}, \cdots, P^{(n)} \} Path={P(0),P(1),⋯,P(n)}
以下举例说明,假设原带权有向图:
10 50 30 90 10 20 70 99 A B C D E F(1)起始矩阵为:
A ( 0 ) = [ A B C D E F A . 10 . 30 90 . B . . 50 . . . C . . . . 10 . D . . 20 . 70 . E . . . . . . F . . . . 99 . ] A^{(0)} = \quad \begin{bmatrix} &A &B &C &D &E &F \\[2ex] A &. &10 &. &30 &90 &. \\[2ex] B &. &. &50 &. &. &. \\[2ex] C &. &. &. &. &10 &. \\[2ex] D &. &. &20 &. &70 &. \\[2ex] E &. &. &. &. &. &. \\[2ex] F &. &. &. &. &99 &. \end{bmatrix} A(0)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡ABCDEFA......B10.....C.50.20..D30.....E90.1070.99F......⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
P ( 0 ) = [ A B C D E F A − 1 0 − 1 0 0 − 1 B − 1 − 1 1 − 1 − 1 − 1 C − 1 − 1 − 1 − 1 2 − 1 D − 1 − 1 3 − 1 3 − 1 E − 1 − 1 − 1 − 1 − 1 − 1 F − 1 − 1 − 1 − 1 5 − 1 ] P^{(0)} = \quad \begin{bmatrix} &A &B &C &D &E &F \\[2ex] A &-1 &0 &-1 &0 &0 &-1 \\[2ex] B &-1 &-1 &1 &-1 &-1 &-1 \\[2ex] C &-1 &-1 &-1 &-1 &2 &-1 \\[2ex] D &-1 &-1 &3 &-1 &3 &-1 \\[2ex] E &-1 &-1 &-1 &-1 &-1 &-1 \\[2ex] F &-1 &-1 &-1 &-1 &5 &-1 \end{bmatrix} P(0)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡ABCDEFA−1−1−1−1−1−1B0−1−1−1−1−1C−11−13−1−1D0−1−1−1−1−1E0−123−15F−1−1−1−1−1−1⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
(2)以 v 0 v_0 v0 即 A 作为中介,A 列全为无穷,则
A ( 1 ) = A ( 0 ) A^{(1)} = A^{(0)} A(1)=A(0)
(3)以 v 1 v_1 v1 即 B 作为中介:
由于
A ( 1 ) [ 0 ] [ 1 ] + A ( 1 ) [ 1 ] [ 2 ] < A ( 1 ) [ 0 ] [ 2 ] ( 10 + 50 < ∞ ) A^{(1)}[0][1] + A^{(1)}[1][2] < A^{(1)}[0][2] \quad(10 + 50 < \infin) A(1)[0][1]+A(1)[1][2]<A(1)[0][2](10+50<∞)
则
A ( 2 ) [ 0 ] [ 2 ] = A ( 1 ) [ 0 ] [ 1 ] + A ( 1 ) [ 1 ] [ 2 ] P ( 2 ) [ 0 ] [ 2 ] = P ( 1 ) [ 1 ] [ 2 ] \begin{aligned} A^{(2)}[0][2] &= A^{(1)}[0][1] + A^{(1)}[1][2] \\ P^{(2)}[0][2] &= P^{(1)}[1][2] \end{aligned} A(2)[0][2]P(2)[0][2]=A(1)[0][1]+A(1)[1][2]=P(1)[1][2]
得到两个新矩阵:
A ( 2 ) = [ A B C D E F A . 10 60 30 90 . B . . 50 . . . C . . . . 10 . D . . 20 . 70 . E . . . . . . F . . . . 99 . ] A^{(2)} = \quad \begin{bmatrix} &A &B &C &D &E &F \\[2ex] A &. &10 &60 &30 &90 &. \\[2ex] B &. &. &50 &. &. &. \\[2ex] C &. &. &. &. &10 &. \\[2ex] D &. &. &20 &. &70 &. \\[2ex] E &. &. &. &. &. &. \\[2ex] F &. &. &. &. &99 &. \end{bmatrix} A(2)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡ABCDEFA......B10.....C6050.20..D30.....E90.1070.99F......⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
P ( 2 ) = [ A B C D E F A − 1 0 1 0 0 − 1 B − 1 − 1 1 − 1 − 1 − 1 C − 1 − 1 − 1 − 1 2 − 1 D − 1 − 1 3 − 1 3 − 1 E − 1 − 1 − 1 − 1 − 1 − 1 F − 1 − 1 − 1 − 1 5 − 1 ] P^{(2)} = \quad \begin{bmatrix} &A &B &C &D &E &F \\[2ex] A &-1 &0 &1 &0 &0 &-1 \\[2ex] B &-1 &-1 &1 &-1 &-1 &-1 \\[2ex] C &-1 &-1 &-1 &-1 &2 &-1 \\[2ex] D &-1 &-1 &3 &-1 &3 &-1 \\[2ex] E &-1 &-1 &-1 &-1 &-1 &-1 \\[2ex] F &-1 &-1 &-1 &-1 &5 &-1 \end{bmatrix} P(2)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡ABCDEFA−1−1−1−1−1−1B0−1−1−1−1−1C11−13−1−1D0−1−1−1−1−1E0−123−15F−1−1−1−1−1−1⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
(3)以 v 2 v_2 v2 即 C 作为中介:
由于
A ( 2 ) [ 0 ] [ 2 ] + A ( 2 ) [ 2 ] [ 4 ] < A ( 2 ) [ 0 ] [ 4 ] ( 60 + 10 < 90 ) A ( 2 ) [ 1 ] [ 2 ] + A ( 2 ) [ 2 ] [ 4 ] < A ( 2 ) [ 1 ] [ 4 ] ( 50 + 10 < ∞ ) A ( 2 ) [ 3 ] [ 2 ] + A ( 2 ) [ 2 ] [ 4 ] < A ( 2 ) [ 3 ] [ 4 ] ( 20 + 10 < 70 ) \begin{aligned} A^{(2)}[0][2] + A^{(2)}[2][4] &< A^{(2)}[0][4] \quad(60 + 10 < 90) \\ A^{(2)}[1][2] + A^{(2)}[2][4] &< A^{(2)}[1][4] \quad(50 + 10 < \infin) \\ A^{(2)}[3][2] + A^{(2)}[2][4] &< A^{(2)}[3][4] \quad(20 + 10 < 70) \end{aligned} A(2)[0][2]+A(2)[2][4]A(2)[1][2]+A(2)[2][4]A(2)[3][2]+A(2)[2][4]<A(2)[0][4](60+10<90)<A(2)[1][4](50+10<∞)<A(2)[3][4](20+10<70)
则
A ( 3 ) [ 0 ] [ 4 ] = A ( 2 ) [ 0 ] [ 2 ] + A ( 2 ) [ 2 ] [ 4 ] = 70 A ( 3 ) [ 1 ] [ 4 ] = A ( 2 ) [ 1 ] [ 2 ] + A ( 2 ) [ 2 ] [ 4 ] = 60 A ( 3 ) [ 3 ] [ 4 ] = A ( 2 ) [ 3 ] [ 2 ] + A ( 2 ) [ 2 ] [ 4 ] = 30 P ( 3 ) [ 0 ] [ 4 ] = P ( 2 ) [ 2 ] [ 4 ] P ( 3 ) [ 1 ] [ 4 ] = P ( 2 ) [ 2 ] [ 4 ] P ( 3 ) [ 3 ] [ 4 ] = P ( 2 ) [ 2 ] [ 4 ] \begin{aligned} A^{(3)}[0][4] &= A^{(2)}[0][2] + A^{(2)}[2][4] &= 70 \\ A^{(3)}[1][4] &= A^{(2)}[1][2] + A^{(2)}[2][4] &= 60 \\ A^{(3)}[3][4] &= A^{(2)}[3][2] + A^{(2)}[2][4] &= 30 \\ P^{(3)}[0][4] &= P^{(2)}[2][4] \\ P^{(3)}[1][4] &= P^{(2)}[2][4] \\ P^{(3)}[3][4] &= P^{(2)}[2][4] \end{aligned} A(3)[0][4]A(3)[1][4]A(3)[3][4]P(3)[0][4]P(3)[1][4]P(3)[3][4]=A(2)[0][2]+A(2)[2][4]=A(2)[1][2]+A(2)[2][4]=A(2)[3][2]+A(2)[2][4]=P(2)[2][4]=P(2)[2][4]=P(2)[2][4]=70=60=30
得到两个新矩阵:
A ( 3 ) = [ A B C D E F A . 10 60 30 70 . B . . 50 . 60 . C . . . . 10 . D . . 20 . 30 . E . . . . . . F . . . . 99 . ] A^{(3)} = \quad \begin{bmatrix} &A &B &C &D &E &F \\[2ex] A &. &10 &60 &30 &70 &. \\[2ex] B &. &. &50 &. &60 &. \\[2ex] C &. &. &. &. &10 &. \\[2ex] D &. &. &20 &. &30 &. \\[2ex] E &. &. &. &. &. &. \\[2ex] F &. &. &. &. &99 &. \end{bmatrix} A(3)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡ABCDEFA......B10.....C6050.20..D30.....E70601030.99F......⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
P ( 3 ) = [ A B C D E F A − 1 0 1 0 2 − 1 B − 1 − 1 1 − 1 2 − 1 C − 1 − 1 − 1 − 1 2 − 1 D − 1 − 1 3 − 1 2 − 1 E − 1 − 1 − 1 − 1 − 1 − 1 F − 1 − 1 − 1 − 1 5 − 1 ] P^{(3)} = \quad \begin{bmatrix} &A &B &C &D &E &F \\[2ex] A &-1 &0 &1 &0 &2 &-1 \\[2ex] B &-1 &-1 &1 &-1 &2 &-1 \\[2ex] C &-1 &-1 &-1 &-1 &2 &-1 \\[2ex] D &-1 &-1 &3 &-1 &2 &-1 \\[2ex] E &-1 &-1 &-1 &-1 &-1 &-1 \\[2ex] F &-1 &-1 &-1 &-1 &5 &-1 \end{bmatrix} P(3)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡ABCDEFA−1−1−1−1−1−1B0−1−1−1−1−1C11−13−1−1D0−1−1−1−1−1E2222−15F−1−1−1−1−1−1⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
(4)以此类推 v n − 1 v_{n-1} vn−1 则求出矩阵 A ( n ) A^{(n)} A(n) 与 P ( n ) P^{(n)} P(n) 。
根据思路,我们需要两个方阵:
存储权值的方阵;
存储路径的方阵(保存路径的上一个顶点)。
同时,我们还要以每个顶点作为中介求解新矩阵。
对矩阵的循环遍历和每个顶点的遍历得出,对于 n 个顶点的图时间复杂度 O(n3) 。