一、最短路径问题
从图中的某个顶点出发,到达另一个顶点的所经过的边的权重之和最小的一条路径。
1.1 两个指定顶点之间的最短路径
问题如下:给出了一个连接若干个城镇的铁路网络,在这个网络的两个指定城镇间,求一条最短铁路线。
1.1.1 Dijkstra算法
迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的。是寻找从一个顶点到其余各顶点的最短路径算法,可用来解决最短路径问题。详细的讲解可参考:数据结构–Dijkstra算法最清楚的讲解
更正:第2、3步中,B(23)应为B(13)。
迪杰斯特拉算法采用贪心算法的策略,将所有顶点分为已标记点和未标记点两个集合,从起始点开始,不断在未标记点中寻找距离起始点路径最短的顶点,并将其标记,直到所有顶点都被标记为止。 需要注意的一点是该方法不能处理带有负权边的图,下面我们举出一个实例并通过迪杰斯特拉方法对其进行求解。
【例】 某公司在六个城市 c 1 , c 2 , c 3 , . . . , c 6 c_1,c_2,c_3,...,c_6 c1,c2,c3,...,c6 中有分公司,从 c i c_i ci 到 c j c_j cj 的直接航程票价记在下述矩阵的 ( i , j ) (i,j) (i,j) 位置上(∞表示无直接航路)。请帮助该公司设计一张城市 c 1 c_1 c1 到其他城市间的票价最便宜的路线图。
用矩阵 a n × n a_{n×n} an×n (n为顶点个数) 存放各边权的邻接矩阵,行向量 p d 、 i n d e x 1 、 i n d e x 2 、 d pd、index_1、index_2、d pd、index1、index2、d 分别用来存放 P P P 标号信息、标号顶点顺序、标号顶点索引、最短通路的值。其中分量
i n d e x 2 ( i ) index_2(i) index2(i) 存放始点到第 i i i 顶点最短通路中第 i i i 顶点的序号; d ( i ) d(i) d(i) 存放由始点到第 i i i 顶点最短通路的值。
求第一个城市到其他城市的最短路径的Matlab程序如下:
clc,clear
a=zeros(6); %邻接矩阵初始化
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25;
a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25;
a(5,6)=55;
a=a+a'; % 两点之间的距离是一样的→对称矩阵
a(a==0)=inf;
pb(1:length(a))=0;pb(1)=1;index1=1;index2=ones(1,length(a));
d(1:length(a))=inf;d(1)=0;
temp=1; %最新的P标号的顶点
while sum(pb)<length(a)
tb=find(pb==0);
d(tb)=min(d(tb),d(temp)+a(temp,tb));
tmpb=find(d(tb)==min(d(tb)));
temp=tb(tmpb(1)); %可能有多个点同时达到最小值,只取其中的一个
pb(temp)=1;
index1=[index1,temp];
temp2=find(d(index1)==d(temp)-a(temp,index1));
index2(temp)=index1(temp2(1));
end
d, index1, index2
运行结果为:
结果表示,最终求得的 c 1 c_1 c1 到 c 2 , . . . , c 6 c_2,...,c_6 c2,...,c6 的最便宜票价分别为35,45,35,25,10。
1.1.2 Matlab函数
【例】 在下图中,用点表示城市,现有 v 1 , v 2 , . . . , v 5 v_1,v_2,...,v_5 v1,v2,...,v5 共5个城市。点与点之间的连线表示城市间有道路相连。连线旁的数字表示道路的长度。现计划从城市 v 1 v_1 v