最短路径

来源:互联网 发布:手游源码吧 编辑:程序博客网 时间:2024/05/05 16:41

目录

  • 目录
  • 概述
  • Dijkstra算法求单源最短路径问题
  • Floyd算法求各顶点之间最短路径问题

概述

若图时带权图,则把从一个定点v0到图中其余任何一个顶点vi的一条路径(可能不止一条)上所经过边上的权值之和定义为该路径上的带权路径长度,把带权路径长度最短的那条路径也称为最短路径

求解最短路径的算法通常都依赖于一种性质,也就是两点之间的最短路径也包含路径上其他顶点间的最短路径。带权有向图G的最短路径问题,一般可分为两类:一是单源最短路径,即求图中某一顶点到其他各顶点的最短路径,可通过经典的Dijkstra算法求解;二是求每一对顶点间的最短路径,可通过Floyd-Warshall算法来求解。

Dijkstra算法求单源最短路径问题

求带权有向图中某个源点到其余各顶点的最短路径,最常用的是Dijkstra算法。该算法设置一个集合S记录已求得的最短路径的顶点,可用一个数组s[]来实现,初始化为0,当s[vi]=1时表示将顶点vi放入S中,初始时把源点v0放入S中。此外,在构造过程中还设置了两个辅助数组:

dist[]:记录了从源点v0到其他各顶点当前的最短路径长度,dist[i]初值为arcs[v0][i].path[]:path[i]表示从源点到顶点i之间的最短路径的前驱节点,在算法结束时,可根据其值追溯得到源点v0到顶点vi的最短路径。

假设从顶点0出发,即v0=0,集合S最初只包含顶点0,邻接矩阵arcs表示带权有向图,arcs[i][j]表示有向边《i,j》的权值,若不存在有向边《i,j》,则arcs[i][j]为∞。Dijkstra算法的步骤如下(不包含path[]的操作):

1)初始化:集合S初始为{0},dist[]的初始值dist[i]=arcs[0][i],i=1,2,...,n-1。2)从顶点集合V-S中选出vj,满足dist[j]=min{dist[i] | vi∈V-S},vj就是当前求得的一条从v0出发的最短路径的终点,令S=S∪{j}。3)修改从v0出发到集合V-S上任一顶点vk可达的最短路径:如果dist[j]+dist[j][k]<dist[k],则令dist[k]=dist[j]+dist[j][k]。

这里写图片描述

这里写图片描述

值得注意的是,如果边上带有负权值,Dijkstra算法并适用

Floyd算法求各顶点之间最短路径问题

求所有顶点之间的最短路径问题描述如下:已知一个各权值均大于0的带权有向图,对每一对顶点vi!=vj,要求求出去vi与vj之间的最短路径和最短路径长度。

Floyd算法基本思想是:递推产生一个n阶方阵序列这里写图片描述,其中A(k)[i][j]表示从顶点vi到顶点vj的路径长度,k表示绕行第k个顶点的运算步骤。初始时,对于任意两个顶点vi和vj,若它们之间存在边,则以此边上的权值作为它们之间的最短路径长度;若它们之间不存在有向边,则以∞作为它们之间的最短路径长度。以后逐步尝试在原路径中加入顶点k(k=0,1,…,n-1)作为中间顶点。如果增加中间顶点后,得到的路径比原路径的长度减少了,则以此新路径代替与路径。算法描述如下:

定义一个n阶方阵序列:A(-1),A(0),...,A(n-1),其中:    A(-1)[i][j]=arcs[i][j]        A(k)[i][j]=Min{A(k-1)[i][j], A(k-1)[i][k]+A(k-1)[k][j]},k=0,1,...,n-1

其中,A(0)[i][j]是从顶点vi到vj、中间顶点是v0的最短路径的长度,A(k)[i][j]是从顶点vi到vj中间顶点的序号不到鱼k的最短路径的长度。

这里写图片描述

这里写图片描述

Floyd算法允许权值为负,但不允许有包含带负权值的边组成回路

1 0
原创粉丝点击