图的最短路径
带权图的最短路径
从某顶点(源点)出发到另一顶点(目的点)的路径中,有一条各边(或弧)权值之和最小的路径称为最短路径。
- 从单源点到其余各点的最短路径 迪杰斯特拉算法(Dijkstra)
- 每一对顶点之间的最短路径 弗洛伊德算法 (Floyd)
迪杰斯特拉(Dijkstra)算法
迪杰斯特拉(Dijkstra)算法:
依最短路径的长度递增的次序求得各条路径。
其中,从源点v0到顶点vi的最短路径是v0到各点路径集合长度中长度最短者。
路径长度最短的最短路径的特点:
在这条路径上,必定只含有一条弧,并且这条弧的权值最小。(设为v0->vk)
下一条路径长度次短的最短路径特点:
它只可能有两种情况:或者是直接从源点到该点vi(只含一条弧);或者是从源点经过顶点vk,再到达vi(由两条弧组成)。
再下一条路径长度次短的最短路径特点:
它可能有两种情况:或者是直接从源点到该点(只含一条弧);或者是从源点经过顶点vk,vi再到达该顶点(由多条弧组成)
其余最短路径:
它或者是直接从源点到该点(只含一条弧);或者是从源点经过已求得最短路径的顶点,再到达该顶点。
迪杰斯特拉(Dijkstra)算法的基本思想:
- 初始时,集合S中仅包含源点v0,集合V-S中包含除源点v0以外的所有顶点。v0到V-S中各顶点的路径长度或者为某个权值(如果它们之间有弧相连),或者为无穷(没有弧相连)。
- 按照最短路径长度递增的次序,从集合V-S中选出到顶点V0路径长度最短的顶点vk加入到S集合中。
- 加入vk之后,为了寻找下一个最短路径,必须修改从v0到集合V-S中剩余所有顶点vi的最短路径。若在最短路径上加入vk之后,使得v0到vi的路径长度比原来没有加入vk时的路径长度短,则修正v0到vi的路径长度为其中较短的。
- 重复以上步骤,直至集合V-S中的顶点全部被加入到集合S中为止。
存储结构
-
带权邻接矩阵用g.arcs[ ] [ ]表示:
用g.arcs[i] [j].adj表示弧<vi,vj>上的权。
-
将顶点分为两组:S,V-S
S中存放已求得最短路径的终点的集合。
-
借助辅助一维数组dist[ ]
若vi属于S,dist[i]表示源点到vi的最短路径长度
若vi属于V-S,dist[i]表示源点到vi的只包括S中的顶点为中间顶点的最短路径。
初始:S={v0},v0为源点
dist[i]=g.arcs[0] [i].adj; (vi属于V-S)
-
二维数组path[] [ ]记录某顶点是否加入到集合S中
如果path[i] [0] = 1,
则表示顶点vi加入到集合S中,并且path[i]所在的行最终记录了源点到vi的最短路径上的各个顶点。
否则,path[i] [0]=0,则表示顶点vi还在集合V-S中。
代码实现:
void <