Oudasheng 2020-01-31
单源最短路径实际是计算源点到其他各个顶点的最短路径的长度,常见算法有dijkstra算法
全局最短路径实际是计算每个源点到其他各个顶点的最短路径的长度,我们可以调用dijkstra算法N次(这样没有Floyd算法快),常见解决全局最短路径的方法是Floyd-Warshall算法,但是Floyd-Warshall算法不能解决负边问题。为了解决负边问题,我们使用Bellman-Ford算法,或者SPFA(Shortest Path Faster Algorithm),SPFA是Bellman-Ford队列优化算法的别称
很多人看到dijkstra、Floyd-Warshall、SPFA、Bellman-Ford会比较头疼。那就仅先掌握2种算法,优先掌握dijkstra、Floyd-Warshall算法,毕竟,这两个收录在教科书内,理论上来说会比较重要。而在PAT解题过程中,也是优先使用Dijstra算法(PAT往往不会因为短路问题超时)。
Dijkstra算法解决单源带权最短路径十分有效。步骤如下:
void Dijstra( Vertex s ) { while(1) { V = 未收录顶点中dist最小者 if( 这样的V不存在 ) break; collected[V] = true; for( V 的每个邻接点 W ) if(collected[W] == false && dist[V] + E<v,w> < dist[W]) { dist[W] = dist[V] + E<v,w>; path[W] = V; } } }
我们为了解决多源最短路径问题,我们可以采用调用N遍Dijsktra算法,这样复杂度T = O(|V|^3+|E|+|V|),也可以采用Floyd-Warshall,复杂度为T = O(|V|^3),在稀疏图,我们可以使用Dijstra算法进行解决,而在稠密图,Floyd会彰显优势。Floyd-Warshall的流程比较简单。流程如下:
void Floyd(){ for(k = 0; k < N; k++) for(i = 0; i < N; i++) for(j = 0; j < N; j++) if(D[i][k] + D[k][j] < D[i][j]) { D[i][j] = D[i][k] + D[k][j]; path[i][j] = k; } }
关于PAT,有这几题是最短路径问题的练习。参考:https://www.liuchuo.net/archives/2502