Bellman–Ford Algorithm 是由 Richard Bellman(DP创始人) 和 Ford 共同创立的,求解单源最短路径问题的一种算法。它的原理是对图进行顶点个数减一次的松弛操作(逐渐逼近最终解的过程),得到所有顶点到源点的最短路径。该算法优于dijkstra的方面在于其边的权值可以是负数(负权环可以无限降低cost)、实现简单,缺点是时间复杂度过高,为O(V*E)。
package datastructure.graph; // A Java program for Bellman-Ford's single source shortest path // algorithm. // A class to represent a connected, directed and weighted graph class BF { // A class to represent a weighted edge in graph class Edge { int src, dest, weight; Edge() { src = dest = weight = 0; } }; int V, E; Edge edge[]; // Creates a graph with V vertices and E edges BF(int v, int e) { V = v; E = e; edge = new Edge[e]; for (int i = 0; i < e; ++i) edge[i] = new Edge(); } // The main function that finds shortest distances from src // to all other vertices using Bellman-Ford algorithm. The // function also detects negative weight cycle void BellmanFord(BF graph, int src) { int V = graph.V, E = graph.E; int dist[] = new int[V]; // Step 1: Initialize distances from src to all other // vertices as INFINITE for (int i = 0; i < V; ++i) dist[i] = Integer.MAX_VALUE; dist[src] = 0; // Step 2: Relax all edges |V| - 1 times. A simple // shortest path from src to any other vertex can // have at-most |V| - 1 edges for (int i = 1; i < V; ++i) { for (int j = 0; j < E; ++j) { int u = graph.edge[j].src; int v = graph.edge[j].dest; int weight = graph.edge[j].weight; if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v]) dist[v] = dist[u] + weight; } } // Step 3: check for negative-weight cycles. The above // step guarantees shortest distances if graph doesn't // contain negative weight cycle. If we get a shorter // path, then there is a cycle. for (int j = 0; j < E; ++j) { int u = graph.edge[j].src; int v = graph.edge[j].dest; int weight = graph.edge[j].weight; if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v]) { System.out.println("Graph contains negative weight cycle"); return; } } printArr(dist, V); } // A utility function used to print the solution void printArr(int dist[], int V) { System.out.println("Vertex Distance from Source"); for (int i = 0; i < V; ++i) System.out.println(i + " " + dist[i]); } // Driver method to test above function public static void main(String[] args) { int V = 5; // Number of vertices in graph int E = 8; // Number of edges in graph BF graph = new BF(V, E); // add edge 0-1 (or A-B in above figure) graph.edge[0].src = 0; graph.edge[0].dest = 1; graph.edge[0].weight = -1; // add edge 0-2 (or A-C in above figure) graph.edge[1].src = 0; graph.edge[1].dest = 2; graph.edge[1].weight = 4; // add edge 1-2 (or B-C in above figure) graph.edge[2].src = 1; graph.edge[2].dest = 2; graph.edge[2].weight = 3; // add edge 1-3 (or B-D in above figure) graph.edge[3].src = 1; graph.edge[3].dest = 3; graph.edge[3].weight = 2; // add edge 1-4 (or A-E in above figure) graph.edge[4].src = 1; graph.edge[4].dest = 4; graph.edge[4].weight = 2; // add edge 3-2 (or D-C in above figure) graph.edge[5].src = 3; graph.edge[5].dest = 2; graph.edge[5].weight = 5; // add edge 3-1 (or D-B in above figure) graph.edge[6].src = 3; graph.edge[6].dest = 1; graph.edge[6].weight = 1; // add edge 4-3 (or E-D in above figure) graph.edge[7].src = 4; graph.edge[7].dest = 3; graph.edge[7].weight = -3; graph.BellmanFord(graph, 0); } } // Contributed by Aakash Hasija
Shortest Path Faster Algorithm (SPFA) - Bellman–Ford的队列改进算法
The Shortest Path Faster Algorithm (SPFA) is an improvement of the Bellman–Ford algorithm which computes single-source shortest paths in a weighted directed graph. The algorithm is believed to work well on random sparse graphs(稀疏图) and is particularly suitable for graphs that contain negative-weight edges.
- Worst case time complexity:
Θ(VE)
SPFA(v):
d[i] = infinity for each vertex i
d[v] = 0
queue q
q.push(v)
while q is not empty
u = q.front()
q.pop()
for each i in adj[u]
if d[i] > d[u] + w(u,i)
then d[i] = d[u] + w(u,i)
if i is not in q
then q.push(i)