从某个源点到其余各顶点的最短路径
先讨论单源点的最短路径问题:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。
Dijkstra算法:按路径长度递增的次序产生最短路径的算法。
首先,引进一个辅助常量D。它的每个分量D[ i ]表示当前所找到的从始点v到每个终点vi的最短路径的长度。它的初态为:若从v到vi有弧,则D[ i ] 为弧上的权值;否则置D为∞。显然,长度为 D[ j ] = Min{ D[ i ] | vi ∈ V} 的路径
就是从c出发的长度最短的一条最短路径。此路径为( v,vj)。
在一般情况下,下一条长度次短的最短路径的长度必是 D[ j ] = Min{D[ i ] | vi ∈ V - S)
其中,D[i]或者是弧(v, vi)上的权值,或者是D[k](vk∈S)和弧(vk,vi)上的权值之和。
根据以上分析,可以得到如下描述的算法:
(1)假设用带权的邻接矩阵arcs来表示带权有向图,arcs[ i ] [ j ]表示弧< vi, vj>上的权值。若< vi, vj>不存在,则置arcs[ i ][ j ]为∞。S为已找到从v处罚的最短路径的终点的集合,他的初始状态为空集。那么,从v出发到图上其余各顶点(终点)vi可能达到的最短路径长度的初值为:
D[ i ] = arcs[ Locate Vex(G, v)[ i ] vi∈V
(2)选择vj,使得D[ j ] = Min{D[ i ] | vi ∈ V-S}
vj就是当前求得的一条从v出发的最短路径的终点。令S = S ∪ { j }
(3)修改从v出发到集合V-S上任一顶点vk可达到的最短路径长度。如果 D[ j ] + arcs[ j ][ k ] < D[ k ] ,则修改D[ k ]为
D[ k ] = D[ j ] + arcs[ j ][ k ]
(4)重复操作(2)(3)共n - 1次。由此求得从v到涂上其余各顶点的最短路径是以路径长度递增的序列。
void ShortesPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D){
for (v = 0; v < G/vexnum; ++v){
final[v] = FALSE; D[v] = G.arcs[v0][v];
for(w = 0; w < g.vexnum; ++w)
P[v][w] = FALSE;
if(D[v] < INFINITY){
P[v][v0] = TRUE;
P[v][v] = TRUE;
}
}
D[v0] = -;
final[v0] = TRUE;
for(i = 1; i < G.vexnum ; ++i){
min = INFINITY;
for(w=0; w < G.vexnum; ++w)
if(!final[w])
if(D[w] < min){
v = w;
min = D[w];
}
for(w = 0; w < g.vexnum; ++w)
if(!final[w]&&(min + G.arcs[v][w] < D[w])){
D[w] = min + G.arcs[v][w];
P[w] = P[v];
p[w][w] = TRUE;
}
}
}
Floyd算法:
通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入两个矩阵,矩阵S中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。矩阵P中的元素b[i][j],表示顶点i到顶点j经过了b[i][j]记录的值所表示的顶点。
假设图G中顶点个数为N,则需要对矩阵D和矩阵P进行N次更新。初始时,矩阵D中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞,矩阵P的值为顶点b[i][j]的j的值。 接下来开始,对矩阵D进行N次更新。第1次更新时,如果”a[i][j]的距离” > “a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”,更新b[i][j]=b[i][0]。 同理,第k次更新时,如果”a[i][j]的距离” > “a[i][k-1]+a[k-1][j]”,则更新a[i][j]为”a[i][k-1]+a[k-1][j]”,b[i][j]=b[i][k-1]。更新N次。
void ShortesPath_FLOYD( MGraph G, PathMatrix &P[ ], DistancMatrix &D )
{
for(v = 0; v < G.vexnum; ++v)
for(w = 0; w < G.vexnum; ++w){
D[v][w] = G.arcs[v][w];
for(u = 0; u < G.vexnum; ++u)
P[v][w][u] = FALSE;
if(D[v][w] < INFINITY){
P[v][w][v] = TRUE;
P[v][w][w] = TRUE;
}
}
for(u = 0; u < G.vexnum; ++u)
for( v = 0; v < G.vexnum; ++w)
if(D[v][u] + D[u][w] < D[v][w]){
D[v][w] = D[v][u] + D[u][w];
for(i = 0; i < G.vexnum; ++i)
P[v][w][i] = P[v][u][i] || P[u][w][i];
}
}