有向图单源非负权值回路最短路径——BellmanFord算法
Posted zqiguoshang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有向图单源非负权值回路最短路径——BellmanFord算法相关的知识,希望对你有一定的参考价值。
BellmanFord算法是一种暴力求解算法O(N3),它考虑所有情况,所以可以允许边的权值为负。(不过不允许出现负权值回路,因为那样会出现无限小)
之所以说它暴力,是因为它求出了每个节点所有长度为1的路径,再求所有长度为2的路径,并更新最短路径数组dist[]和path[],如此迭代直至求到长度n-1的路径。(n为图节点个数)
整体来看,每个节点纵向比较,从1到n-1长度的路径中取最小值作为最终路径长度。
因为它考虑了所有情况,所以负边也可以算出。
因为暴力,复杂度比Dijkstra高一个数量级,达到了O(N3)。不过Dijkstra不能计算负边,所以倒也划算。
下面给出算法。
1 public int minPathBF(int source, int target){ 2 if (source == target){ 3 System.out.println("(" + source + " " + target + ")"); 4 return 0; 5 } 6 int[] path = bellmanFord(source); 7 int result = 0; 8 String way = ""; 9 while (-1 != path[target]){ 10 way = "(" + path[target] + " " + target + ") " + way; 11 result += graph[path[target]][target]; 12 target = path[target]; 13 } 14 System.out.println(way); 15 return result; 16 } 17 18 private int[] bellmanFord(int vertex){ 19 int[] path = new int[numVertices]; 20 int[] dist = new int[numVertices]; 21 //initial 22 for (int i = 0; i < numVertices; i++) { 23 if (graph[vertex][i] != 0 && graph[vertex][i] < 1000){ 24 dist[i] = graph[vertex][i]; 25 path[i] = vertex; 26 }else { 27 dist[i] = 1000; 28 path[i] = -1; 29 } 30 } 31 for (int i = 2; i < numVertices; i++){// calculate to n-1 path length 32 for (int j = 0; j < numVertices; j++){// calculate num j vertex path 33 if (j != vertex){ 34 for (int k = 0; k < numVertices; k++) { 35 if (k != vertex && graph[k][j] != 0 && graph[k][j] < 1000 && dist[k] < 1000){ 36 if (graph[k][j] + dist[k] < dist[j]){ 37 dist[j] = dist[k] + graph[k][j]; 38 path[j] = k; 39 } 40 } 41 } 42 } 43 } 44 } 45 return path; 46 }
以上是关于有向图单源非负权值回路最短路径——BellmanFord算法的主要内容,如果未能解决你的问题,请参考以下文章