为了论述方便,本文借助下图,介绍网络弧集 E E E和网络权矩阵 W W W的概念。
(上述网络图上标的数字为各段弧的权值,该图左侧为无向网络图,右侧为有向网络图。)
对于上述无向网络图而言,网络弧集 E 1 = [ ( v 1 , v 2 ) , ( v 1 , v 4 ) , ( v 2 , v 1 ) , ( v 2 , v 4 ) , ( v 2 , v 3 ) , ( v 3 , v 2 ) , ( v 3 , v 4 ) , ( v 4 , v 1 ) , ( v 4 , v 2 ) , ( v 4 , v 3 ) ] E_1=[(v_1,v_2),(v_1,v_4),(v_2,v_1),(v_2,v_4),(v_2,v_3),\\(v_3,v_2),(v_3,v_4),(v_4,v_1),(v_4,v_2),(v_4,v_3)] E1=[(v1,v2),(v1,v4),(v2,v1),(v2,v4),(v2,v3),(v3,v2),(v3,v4),(v4,v1),(v4,v2),(v4,v3)],
对于上述有向网络图而言,网络弧集 E 2 = [ ( v 1 , v 2 ) , ( v 1 , v 4 ) , ( v 2 , v 3 ) , ( v 2 , v 4 ) , ( v 3 , v 4 ) ] E_2=[(v_1,v_2),(v_1,v_4),(v_2,v_3),(v_2,v_4),(v_3,v_4)] E2=[(v1,v2),(v1,v4),(v2,v3),(v2,v4),(v3,v4)]。
由此可见,集合 E E E就是网络图的所有弧集合。
网络权矩阵 W = ( W i j ) n × n W=(W_{ij})_{n×n} W=(Wij)n×n,其中,
当 ( v i , v j ) ∈ E (v_i,v_j)∈ E (vi,vj)∈E时, W i j = L i j W_{ij}=L_{ij} Wij=Lij, L i j L_{ij} Lij为弧 ( v i , v j ) (v_i,v_j) (vi,vj)的权;
W i i = 0 , i = 1 , 2 , … , n W_{ii}=0,i=1,2,…,n Wii=0,i=1,2,…,n;
当 ( v i , v j ) ∉ E (v_i,v_j)∉E (vi,vj)∈/E且 i ≠ j i≠j i=j时, W i j = i n f W_{ij}=inf Wij=inf,( i n f inf inf为无穷大, n n n为网络节点个数)
则按上述规定,上面无向网络图和有向网络图的权矩阵分别为
W 1 = [ 0 4 i n f 5 4 0 3 5 i n f 3 0 2 5 5 2 0 ] W_1=\begin{bmatrix} 0 & 4 & inf & 5 \\ 4 & 0 & 3 & 5 \\ inf & 3 & 0 & 2 \\ 5 & 5 & 2 & 0\end{bmatrix} W1=⎣⎢⎢⎡04inf54035inf3025520⎦⎥⎥⎤,
W 2 = [ 0 4 i n f 5 i n f 0 3 1 i n f i n f 0 2 i n f i n f i n f 0 ] W_2=\begin{bmatrix} 0 & 4 & inf & 5 \\ inf & 0 & 3 & 1 \\ inf & inf & 0 & 2 \\ inf & inf & inf & 0 \end{bmatrix} W2=⎣⎢⎢⎡0infinfinf40infinfinf30inf5120⎦⎥⎥⎤
由于上述网络图均只有4个结点,故网络的权矩阵均为4阶矩阵。
①求任意两结点的最短路径;
②有向图、无向图、混合图。
直接在网络图的权矩阵 W W W中用插入顶点的方法依次递推地构造出 n n n个矩阵 D ( 1 ) , D ( 2 ) , … , D ( n ) D(1),D(2),…,D(n) D(1),D(2),…,D(n), D ( n ) D(n) D(n)是网络图的最短距离矩阵,同时引入一个路由矩阵记录任意两点之间的最短路径。
设 D i j D_{ij} Dij为结点 v i v_i vi到 v j v_j vj的距离; P i j P_{ij} Pij为结点 v i v_i vi到 v j v_j vj路径上 v i v_i vi的后继点; W W W为权矩阵。
下面给出一个例子,网络图如下:
可以看出,上图为无向网络图,其结点个数 n = 7 n=7 n=7,权矩阵为:
W = [ 0 4 6 5 i n f i n f i n f 4 0 1 i n f 7 i n f i n f 6 1 0 2 5 4 i n f 5 i n f 2 0 i n f i n f i n f i n f 7 5 i n f 0 1 6 i n f i n f 4 5 1 0 8 i n f i n f i n f i n f 6 8 0 ] W=\begin{bmatrix} 0 & 4 & 6 & 5 & inf & inf & inf \\ 4 & 0 & 1 & inf & 7 & inf & inf \\ 6 & 1 & 0 & 2 & 5 & 4 & inf \\ 5 & inf & 2 & 0 & inf & inf & inf \\ inf & 7 & 5 & inf & 0 & 1 & 6 \\ inf & inf & 4 & 5 &1 & 0 & 8 \\ inf & inf & inf & inf &6 & 8 & 0 \end{bmatrix} W=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡0465infinfinf401inf7infinf610254inf5inf20inf5infinf75inf016infinf4inf108infinfinfinf680⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤
下面利用MATLAB编写程序求其最短距离矩阵、路由矩阵以及任给两结点之间的最短距离和路径。
%% FileName:Floyd.m
%% Date:2020-4-13
%% Writer:Yida
%% Function:输出网络图的最短距离矩阵和路由矩阵,指定两结点间的最短距离及其路径
%%
function [D, P, dis, path] = Floyd(W, start, stop) %start为指定起始结点,stop为指定终止结点
D = W; %最短距离矩阵赋初值
n = length(D); %n为结点个数
P = zeros(n,n); %路由矩阵赋初值
for i = 1:n
for j = 1:n
P(i,j) = j;
end
end
for k = 1:n
for i = 1:n
for j = 1:n
if D(i,k) + D(k,j) < D(i,j)
D(i,j) = D(i,k) + D(k,j); %核心代码
P(i,j) = P(i,k);
end
end
end
end
if nargin ~= 3
errordlg('参数个数输入有误!', 'Warning!')
else
dis = D(start, stop); %指定两结点间的最短距离
m(1) = start;
i = 1;
while P(m(i),stop) ~= stop
k = i + 1;
m(k) = P(m(i),stop);
i = i + 1;
end
m(i+1) = stop;
path = m; %指定两结点之间的最短路径
end
%%
调用上述函数求该网络图的最短距离矩阵,并确定结点 v 1 v_1 v1到 v 7 v_7 v7的最短距离对应的路径,程序如下:
W = ones(7) * inf; %权矩阵初始化
for i = 1:7
W(i,i) = 0;
end
W(1,2) = 4; W(1,3) = 6; W(1,4) = 5;
W(2,1) = 4; W(2,3) = 1; W(2,5) = 7;
W(3,1) = 6; W(3,2) = 1; W(3,4) = 2; W(3,5) = 5; W(3,6) = 4;
W(4,1) = 5; W(4,3) = 2; W(4,6) = 5;
W(5,2) = 7; W(5,3) = 5; W(5,6) = 1; W(5,7) = 6;
W(6,3) = 4; W(6,4) = 5; W(6,5) = 1; W(6,7) = 8;
W(7,5) = 6; W(7,6) = 8; %修改元素后W为权矩阵
pre_path = {'v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7'}; %本例中网络图结点
start = 1; %起始节点为v1
stop = 7; %终止结点为v7
[D, P, dis, path] = Floyd(W, start, stop); %调用函数求解
fprintf('\n最短距离矩阵 D =\n\n')
disp(D)
fprintf('\n路由矩阵 P =\n\n')
disp(P)
fprintf('结点%s到%s的最短距离为:%f\n\n', pre_path{start}, pre_path{stop}, dis)
fprintf('结点%s到%s的最短路径为:\n\n', pre_path{start}, pre_path{stop}) %输出两给定结点间的最短路径
for i = 1:length(path)-1
fprintf('%s', pre_path{path(i)})
fprintf(' -> ')
end
fprintf('%s.\n', pre_path{path(length(path))})
程序运行结果如下:
最短距离矩阵 D =
0 4 5 5 10 9 16
4 0 1 3 6 5 12
5 1 0 2 5 4 11
5 3 2 0 6 5 12
10 6 5 6 0 1 6
9 5 4 5 1 0 7
16 12 11 12 6 7 0
路由矩阵 P =
1 2 2 4 2 2 2
1 2 3 3 3 3 3
2 2 3 4 5 6 5
1 3 3 4 6 6 6
3 3 3 6 5 6 7
3 3 3 4 5 6 5
5 5 5 5 5 5 7
结点v1到v7的最短距离为:16.000000
结点v1到v7的最短路径为:
v1 -> v2 -> v3 -> v5 -> v7.
由程序运行结果知,该无向网络图的最短距离矩阵为:
D = [ 0 4 5 5 10 9 16 4 0 1 3 6 5 12 5 1 0 2 5 4 11 5 3 2 0 6 5 12 10 6 5 6 0 1 6 9 5 4 5 1 0 7 16 12 11 12 6 7 0 ] D=\begin{bmatrix} 0&4&5&5&10&9&16 \\ 4&0&1&3&6&5&12 \\ 5&1&0&2&5&4&11 \\ 5&3&2&0&6&5&12 \\ 10&6&5&6&0&1&6 \\ 9&5&4&5&1&0&7 \\ 16&12&11&12&6&7&0 \end{bmatrix} D=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡04551091640136512510254115320651210656016954510716121112670⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤
结点 v 1 v_1 v1到 v 7 v_7 v7的最短距离为16,其最短路径为: v 1 − > v 2 − > v 3 − > v 5 − > v 7 v_1->v_2->v_3->v_5->v_7 v1−>v2−>v3−>v5−>v7。
值得注意的是,上述由结点 v 1 v_1 v1到 v 7 v_7 v7的最短距离确实为16,但是,由 v 1 v_1 v1到 v 7 v_7 v7的最短距离对应的路径却不止一条(另一条为: v 1 − > v 2 − > v 3 − > v 6 − > v 5 − > v 7 v_1->v_2->v_3->v_6->v_5->v_7 v1−>v2−>v3−>v6−>v5−>v7),这是为什么呢?让我们回到上述算法步骤第2步,要求 ∀ i , j , 若 D i k + D k j < D i j {\forall}i,j,若D_{ik}+D_{kj}
下图就不存在1号顶点到3号顶点的最短路径,因为在 1 − > 2 − > 3 − > 1 − > 2 − > 3 − > … 1 − > 2 − > 3 1->2->3->1->2->3->…1->2->3 1−>2−>3−>1−>2−>3−>…1−>2−>3这样的路径中,每绕一次 1 − > 2 − > 3 1->2->3 1−>2−>3这样的环,最短路径就会减少1,永远找不到最短路径。所以,Floyd算法不能解决带有"负权回路"(或者叫"负权环")的网络图,因为带有"负权回路"的网络图没有最短路径。
结束语:本文根据理解编写,如有错误或不妥之处,请指正!
声明:更详细介绍请看本人简文弗洛伊德(Floyd)算法详解 | MATLAB实现
觉得不错?关注一下,点个赞呗!