赞
踩
目录
最短路径问题的引出:
最短路径问题一般分为两类:一是单源最短路径,即求图中某一顶点到其他顶点的最短路径,可通过Dijkstra(迪杰斯特拉)算法求解;二是求每一对顶点间的最短路径,可通过Floyd( 弗洛伊德)算法求解。
这里讨论的最短路径问题主要是针对带权有向图而言的,当然也可以认为带权无向图是顶点间有对称弧的带权有向图,无权图的边的权默认为1。我们把带权有向图问题解决了,这些特殊问题也能解决。
称路径上的第一个顶点为源点,最后一个顶点为终点。
基本思想
- 对于与源点直接相连的顶点,它们之间权值最小的那个边对应的顶点的最短路径就一定是这条边。(因为不可能通过其他路径从到 比直接从到更近了)
- 每次确定了到的顶点的最短路径后,更新未确定的顶点的目前最短路径长度(可通过已经确定的最短路径了),然后我们再选择目前带权路径长度最短的那个未确定的顶点作为我们接下来确定了最短路径长度的新顶点。
- 以此类推,共操作n-1次我们求得了源点到其它所有顶点的最短路径长度。
实现细节
- dist[]记录从源点到其它各顶点当前的最短路径长度,它的初始状态为:若从到 有弧,则dist[i]为弧上的权值;否则置dist[i]为无穷。
- path[]数组用来表示从源点到顶点i之间的最短路径的前驱顶点。在算法结束时,可以根据其值追溯得到源点 到的最短路径。
- 设置一个集合S记录已求得的最短路径的顶点,初始时把源点放入集合S中。
- 集合S每并入一个新顶点,都要修改源点 到集合(V-S) “V减去S”,中的顶点的当前的最短路径长度值。
算法步骤
- 初始化:假设顶点0为源点,集合S初始化为{0},dist[]的初始值dist[i]=arcs[0][i]。
- 从顶点集合V-S中选出 ,满足dist[i]=Min{dist[i] | ∈V-S}, 就是当前求得的一条从出发的最短路径的终点,令S=S∪{i}。
修改源点 到集合(V-S)中的顶点的当前的最短路径长度值:若dist[i]+arcs[i][k]<dist[k],则更新dist[k]=dist[i]+arcs[i][k],k为集合(V-S)中的任一顶点。
重复步骤2~3操作共n-1次,直到所有的顶点都包含在S中。
算法分析
- Dijkstra算法很明显是一个贪心策略,一个问题的整体最优解可通过一系列局部的最优解达到,并且每次的选择最优解依赖以前作出的选择,但不依赖后面要作出的选择。
- 如果我们只需要求源点到某一个特点顶点的最短路径,但这个问题和求解和源点到其它所有顶点的最短路径一样复杂,因为这个问题的最优解依赖于其他问题的最优解,所以时间复杂度也为O(||)。
基本思想
- 递推产生一个n阶方阵序列,,...,,...,,其中[i][j]是从顶点Vi到Vj、中间顶点的序号不大于K的最短路径的长度。
- Floyd算法是一个迭代的过程,每迭代一次,在从Vi到Vj的路径上就多考虑了一个顶点:经过n次迭代后,所得到的[i][j]就是Vi到Vj的最短路径长度,即方阵 中就保存了任意一对顶点之间的最短路径长度。
算法步骤
初始化:方阵 [i][j]=arcs[i][j]
- 将V0作为中间顶点,对于所有顶点对{i,j},如果有[i][j]>[i][0]+[0][j] ,则更新 [i][j]为 [i][0]+[0][j]。更新后的方阵标记为。
- 将V1作为中间顶点,继续检测所有顶点对{i,j}。更新后的方阵标记为。
- 将剩余顶点作为中间顶点重复步骤2操作,共操作n次得到的方阵就保存了n个顶点中任意一对顶点之间的最短路径长度。
算法分析
- Floyd算法运用到了动态规划(DP)的思想,通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推的方式去解决。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。