7.3 最短路径算法

最短路径算法在数学建模中的应用相当广泛,数学建模竞赛中的赛题中也经常出现,如2007年的“乘公交,看奥运”、2011年的“交巡警服务平台的设置与调度”等.

在一个网络中,如果两个结点之间有直接的因果关系,则这两个结点直接连通,在连接两个结点的弧上标上它的代价或权,值得注意的是这样的代价不一定是对称的,即A 到B 的代价不一定等于B 到A 的代价,实际问题中以行船为例,有顺水和逆水的区别.在图G 中,给出两个结点求这样一条最短的路径,使经过这条路径上的代价之和最小,这就是最短路径问题.

7.3.1 Dijkstra算法

A 基本概念

在无向图G =(V,E )中,假设每条边E [i ]的长度为w [i ],找到由顶点u 0 到其余各点的最短路径.迪克斯特拉算法用来解决从顶点u 0 出发到其余顶点的最短路径,该算法按照最短路径长度递增的顺序产生最短路径.

B 算法描述

迪克斯特拉(Dijkstra)算法的基本思想是按距u 0 从近到远为顺序,依次求得u 0 到G 的各顶点的最短路径和距离,直至v 0 (或直至G 的所有顶点),算法结束.为避免重复并保留每一步的计算信息,采用了标号算法.下面是该算法.

(i)令l (u 0 )=0,对v ≠u 0 ,令l (v )=∞,S 0 ={u 0 },i =0.

(ii)对每个7.3 最短路径算法 - 图1 ,用7.3 最短路径算法 - 图2 代替l (v ).计算7.3 最短路径算法 - 图3 ,把达到这个最小值的一个顶点记为u i +1 ,令7.3 最短路径算法 - 图4

(iii)若i =|V|-1,停止;若i<|V|-1,用i +1代替i ,转(ii).

算法结束时,从u 0 到各顶点v 的距离由v 的最后一次的标号l (v )给出.在v 进入Si 之前的标号l (v )叫T 标号,v 进入Si 时的标号l (v )叫P 标号.算法就是不断修改各顶点的T 标号,直至获得P 标号.若在算法运行过程中,将每一顶点获得P 标号所由来的边在图上标明,则算法结束时,u 0 至各顶点的最短路径也在图上标示出来了.

C Matlab程序

function[weight,path]=dijkstar(a)

pb(1∶length(a))=0;%pb记录是否标号

pb(1)=1;

index1=1;%index1记录标号顺序

index2=ones(1,length(a));%index2记录标号的前一结点号,便于最后寻找路径

d(1∶length(a))=inf;%d中初始为inf,后面再修改.

d(1)=0;%第一个顶点到自身的距离自然是0

temp=1;%初始由第一点开始寻找

while sum(pb)<size(a,2)%终止条件为pb中的点全部标号(用1表示已标号,0表示未标号)

tb=find(pb==0);%找出未标号的点向量

d(tb)=min(d(tb),d(temp)+a(temp,tb));%替换过程默认1号点为始发点

tmpb=find(d(tb)==min(d(tb)));%找出最小的距离进行标号

temp=tb(tmpb(1));%同上可能有多个点的权值达到最小,故取1号点对应的点号

pb(temp)=1;%正式标号

index1=[index1,temp];%将标号的点归入index1中,在下次搜索中失去候选资格

index=index1(find(d(index1)==d(temp)-a(temp,index1)));

%以下程序全为找到路径的向量

7.3 最短路径算法 - 图5

D 实例

例:对下列带权无向图,利用上述函数进行计算1点到其他各点的距离和路径.

7.3 最短路径算法 - 图6

7.3 最短路径算法 - 图7

e给出了从1点到其他点的最短距离,t给出了从1点到其他点的路线,t的第6个元素是5,第5个元素是2,第2个元素是1,故1→6的路径为1→2→5→6.

7.3.2 Floyd算法

A 基本概念

Floyd算法是求任意两结点间的最短路径.显然,Floyd算法可以使用dijkstra算法n 次完成,时间复杂度是O (n ^3).

Floyd还提出过另一个算法,同样是O (n ^3)的复杂度,但形式上更简单些.

要求的解是一个矩阵S [N ×N ],其中S [i ][j ]表示结点i 到j的最短路径,算法很像动态规划算法,甚至更简单些,不同的是这里规划的是一个矩阵,而不是简单的数组.

B Floyd算法过程

Floyd算法过程描述如下:

Step1:首先S 以边集M 初始化,得到所有的直接连通代价;

Step2:依次考虑第k 个结点,对于S 中的每一个S [i ][j ],判断是否满足:

S [i ][j ]>S [i ][k ]+S [k ][j ],如果满足则用S [i ][k ]+S [k ][j ]代替S [i ][j ],此为第k 步;

Step3:k 循环取遍所有结点,算法结束时,S 为最终解.

C Floyd算法的Matlab程序

function[shortpath,nextnode]=floyd(vex,k)

%vex是邻接矩阵,shortpath返回最短路径矩阵,nextnode返回路线经过的结点构成的矩阵

7.3 最短路径算法 - 图8

D 实例

对于上述例子,用floyd算法计算任意两点的最短路径和路线.

M=inf;

7.3 最短路径算法 - 图9

[S,R]=floyd(a,6);

通过上程序计算得:

7.3 最短路径算法 - 图10

结果说明:

S 矩阵第1行,第6列的值为6,表示从第1点到第6点的最短路径为6. R 矩阵第1行第6列的值为2,第2行第6列的值为5,而第5行第6列的值为6,因此,1—6的最短路线为:1—2—5—6.

S 矩阵第3行,第4列的值为5,表示从第3点到第4点的最短路径为5. R 矩阵第3行第4列的值为2,第2行第4列的值为4,因此,3—4的最短路线为:3—2—4.