7.1 最短路径问题
最短路径问题分为:单源最短路径和多源最短路径。
单源最短路径:
单源无全图的算法思想:从源点开始一圈一圈往外扩展,依次找到与源点距离为1的,与源点距离为2的节点,对广度优先搜索(BFS)稍作修改即可。
void Unweighted( Vertex S ){
int Dest[N] = {-1};
Vertex Path[];
EnQueue( S,Q );
Dest[S] = 0;
while( !IsEmpty Q ){
V = DelQueue(Q);
for(V的每一个邻接点W){
if( Dist[W] == -1){
//到W的距离等于到V的距离加1
Dist[W] = Dist[V]+1;
//到达W的最短路径必须经过V
Path[W] = V;
}
}
}
}
单源有权图的算法(dijkstra算法):有一个集合S,它里面收录了源点和已经找到最短路径的点,按照距离非递减的顺序依次把所有的点都收录到S里面。
//需要把Dist初始化为正无穷,Path初始化为-1
void Dijkstra(VerTex V){
Dest[V] = 0;
Collected[V] = true;
for(V的每一个邻接点W){
//E<V,W>bi表示V到W的距离,也就是权重。
Dest[W] = E<V,W>;
}
while(1){
V = 还未收录的节点的Dest最小的节点。
if(所有的节点都被收录)break;
Collected[V] = true;
for(V的每一个邻接点){
if( Collected[W] == false ){
if(Dist[V] + E<V,W> < Dist[W]){
Dist[W] = Dist[V] + E<V,W>;
Path[W] = V;
}
}
}
}
}
多源最短路径:
方法一:可以直接把单源最短路径的方法对每一个节点都调用一遍(对稀疏图效果好)。
方法二:Floyd算法
bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum] )
{
Vertex i, j, k;
/* 初始化 */
for ( i=0; i<Graph->Nv; i++ )
for( j=0; j<Graph->Nv; j++ ) {
D[i][j] = Graph->G[i][j];
path[i][j] = -1;
}
for( k=0; k<Graph->Nv; k++ )
for( i=0; i<Graph->Nv; i++ )
for( j=0; j<Graph->Nv; j++ )
if( D[i][k] + D[k][j] < D[i][j] ) {
D[i][j] = D[i][k] + D[k][j];
if ( i==j && D[i][j]<0 ) /* 若发现负值圈 */
return false; /* 不能正确解决,返回错误标记 */
path[i][j] = k;
}
return true; /* 算法执行完毕,返回正确标记 */
}