1、第六讲 图(下) 浙江大学 陈 越6.1 最短路径问题最短路径问题的抽象 在网络中,求两个不同顶点之间的所有路径 中,边的权值之和最小的那一条路径 这条路径就是两点之间的最短路径 (Shortest Path ) 第一个顶点为源点 (Source ) 最后一个顶点为终点 (Destination )问题分类 单源最短路径问题:从某固定源点出发,求其 到所有其他顶点的最短路径 (有向)无权图 (有向)有权图 多源最短路径问题:求任意两顶点间的最短路 径无权图的单源最短路算法 v 1 v 2 v 6 v 7 v 3 v 4 v 5 0 0: v 3 1: v 1 and v 6 1 1 2: v
2、2 and v 4 2 2 3: v 5 and v 7 3 3 BFS ! James Bond 从孤岛跳上岸,最少需要跳多少步? 按照递增(非递减)的顺序找出到各个顶 点的最短路无权图的单源最短路算法 void BFS ( Vertex S ) visitedS = true; Enqueue(S, Q); while(!IsEmpty(Q) V = Dequeue(Q); for ( V 的每个邻接点 W ) if ( !visitedW ) visitedW = true; Enqueue(W, Q); distW = S 到W的最短距离 distS = 0 pathW = S 到W的
3、路上经过的某顶点 void Unweighted ( Vertex S ) Enqueue(S, Q); while(!IsEmpty(Q) V = Dequeue(Q); for ( V 的每个邻接点 W ) if ( distW=-1 ) distW = distV+1; pathW = V; Enqueue(W, Q); T = O( |V| + |E| )有权图的单源最短路算法 v 1 v 2 v 6 v 7 v 3 v 4 v 5 2 4 2 13 1 0 2 5 8 4 6 1 v 1 v 2 v 6 v 7 v 3 v 4 v 5 2 4 2 1 3 10 2 5 8 4 6 1
4、 负值圈 (negative-cost cycle) 按照 递增的顺序找出到各个顶点的最短路 算法有权图的单源最短路算法 Dijkstra 算法 令S=源点s + 已经确定了最短路径的顶点v i 对任一未收录的顶点v,定义distv 为s 到v 的最 短路径长度,但该路径仅经过S 中的顶点。即路径 s (v i S) v的最小长度 若路径是按照递增(非递减)的顺序生成的,则 真正的最短路必须只经过S中的顶点(为什么?) 每次从未收录的顶点中选一个dist最小的收录(贪心) 增加一个v进入S,可能影响另外一个w 的dist值! distw = mindistw, distv + 的权重有权图的单
5、源最短路算法 void Dijkstra( Vertex s ) while (1) V = 未收录顶点中dist 最小者; if ( 这样的V不存在 ) break; collectedV = true; for ( V 的每个邻接点 W ) if ( collectedW = false ) if ( distV+E; pathW = V; /* 不能解决有负边的情况 */ T = O( ? )有权图的单源最短路算法 方法1:直接扫描所有未收录顶点 O( |V| ) T = O( |V| 2 + |E| ) 方法2:将dist存在最小堆中 O( log|V| ) 更新distw的值 O(
6、log|V| ) T = O( |V| log|V| + |E| log|V| ) = O( |E| log|V| ) 对于稠密图效果好 对于稀疏图效果好多源最短路算法 方法1:直接将单源最短路算法调用|V| 遍 T = O( |V| 3 + |E| |V|) 方法2: T = O( |V| 3 ) 对于稀疏图效果好 算法 对于稠密图效果好多源最短路算法 Floyd 算法 D k ij = 路径 i l k j 的最小长度 D 0 , D 1 , , D |V|-1 ij即给出了i 到j的真正最短距离 最初的D -1 是什么? 当D k-1 已经完成,递推到D k 时: 或者k 最短路径 i
7、l k j ,则D k = D k-1 或者k 最短路径 i l k j ,则该路径必定由两 段最短路径组成 : D k ij=D k 1 ik+D k 1 kj多源最短路算法 void Floyd() for ( i = 0; i N; i+ ) for( j = 0; j N; j+ ) Dij = Gij; pathij = -1; for( k = 0; k N; k+ ) for( i = 0; i N; i+ ) for( j = 0; j N; j+ ) if( Dik + Dkj Dij ) Dij = Dik + Dkj; pathij = k; T = O( |V| 3 )