Today, I have a deeper understanding of the Bellman-Ford algorithm. Its negative weight loop can be used to determine the current loop. It is determined based on the last path of the loop.
Dijkstra is an effective algorithm for processing the single-source shortest path, but it is limited to the case that the edge weight is not negative. If an edge with a negative weight is displayed in the graph, the Dijkstra algorithm will become invalid, the obtained shortest path may be incorrect. At this time, we need to use other algorithms to solve the shortest path. The Bellman-Ford algorithm is one of the most commonly used algorithms. The algorithm was invented by American mathematician Richard Bellman and Lester Ford. The flow of the Bellman-Ford algorithm is as follows:
Given graph G (V, E) (where V and E are vertex sets and edge sets of graph G respectively), Source Vertex s,
- Array distant [I] records the path length from the source point S to the vertex I. The initialized array distant [N] is, and distant [s] is 0;
-
The following operations can be performed cyclically for up to n-1 times, and N is the number of vertices:
For each edge e (u, v), if distant [u] + W (u, v) <distant [v], then distant [v] = distant [u] + W (u, v ). W (u, v) is the weight of edge e (u, v;
If the preceding operation does not update distant, it indicates that the shortest path has been searched, or some vertices are not reachable. Otherwise, execute the next loop;
- To check whether a negative loop exists in the graph, that is, the loop with the sum of weights less than 0. For each edge e (u, v), if there is an edge of distant [u] + W (u, v) <distant [v], there is a negative loop in the figure, that is, the shortest path of a single source cannot be obtained by modifying the image. Otherwise, the shortest path length from the Source Vertex s to each vertex is recorded in the array distant [N.
We can see that the time complexity of the Bellman-Ford Algorithm for Finding the single-source shortest path is O (V * E ).
First, we will introduce the relaxation calculation. For example:
Before the relaxation calculation, the value of point B is 8, but the value of Point A is smaller than the value of point B (8) by adding the weight of 2 on the edge, the value of point B is reduced to 5. The significance of this process is to find a shorter route to point B, which first passes through point A and then reaches Point B through the edge with a weight of 2.
Of course
The value of point B is not modified, because 3 + 4> 6.
The bellman-Ford algorithm can be roughly divided into three parts:
First, Initialize all vertices. Save a value for each vertex, indicating the distance from the origin to this vertex. Set the value of the origin to 0, and set the value of other vertices to infinity (indicating that the origin cannot be reached ).
Second, perform a loop. The subscripts of the loop are from 1 to n-1 (N is equal to the number of vertices in the graph ). In the loop, traverse all edges for relaxation calculation.
Third, traverse all the edges (u, v) on the way to determine whether such a situation exists:
D (v)> d (u) + W (u, v)
The return value is false, indicating that there is a loop with a negative permission from the source point.
The reason for the third part is that if there is a loop with the right to reach from the source point as negative. Therefore, the shortest path cannot be obtained because it cannot be converged.
Consider the following figure:
After the first traversal, the value of point B is changed to 5, and the value of point C is changed to 8. At this time, pay attention to the edge with a weight of-10 and the existence of this edge, the value of vertex A changes to-2. (8 +-10 =-2)
After the second traversal, the value of point B changes to 3, point C changes to 6, and point a changes to-4. It is precisely because there is a negative edge in the loop that the values of each vertex keep decreasing after each traversal.
Let's look back at the third part of the Bellman-Ford algorithm. traverse all edges and check whether d (v)> d (u) + W (u, v) exists ). Because the number of cycles in the second part is fixed, if convergence is not possible, it can be checked out in the third part. For example
In this case, the value of vertex A is-2, the value of vertex B is 5, and the weight of edge AB is 5, 5,>-2 + 5. Check that this edge does not converge.
Therefore, the bellman-Ford algorithm can solve the single-source shortest path problem of an edge with a negative number in the graph.
I personally feel that the introduction to algorithms is very good. I will post this chapter to share with you:
24.1 The Bellman-Ford Algorithm
TheBellman-Ford AlgorithmSolves the single-source shortest-paths problem in the general case in which edge weights may be negative. Given a weighted, Directed GraphG= (V,E) With sourceSAnd Weight FunctionW:E→R, The bellman-Ford algorithm returns a Boolean value indicating whether or not there is a negative-weight cycle that is reachable from the source. if there is such a cycle, the algorithm indicates that no solution exists. if there is no such cycle, the algorithm produces the shortest paths and their weights.
The algorithm uses relaxation, progressively decreasing an estimateD[V] On the weight of a shortest path from the sourceSTo each vertexVεVUntil it achieves the actual shortest-path weightDelta(S,V). The algorithm returns true if and only if the graph contains no negative-weight cycles that are reachable from the source.
BELLMAN-FORD(G, w, s)1 INITIALIZE-SINGLE-SOURCE(G, s)2 for i ← 1 to |V[G]| - 13 do for each edge (u, v) ∈ E[G]4 do RELAX(u, v, w)5 for each edge (u, v) ∈ E[G]6 do if d[v] > d[u] + w(u, v)7 then return FALSE8 return TRUE
Figure 24.4 shows the execution of the Bellman-Ford Algorithm on a graph with 5 vertices. After initializingDAnd π values of all vertices in line 1, the algorithm makes |V|-1 passes over the edges of the graph. Each pass is one iteration ofForLoop of lines 2-4 and consists of relaxing each edge of the graph once. figures 24.4 (B)-(e) show the state of the algorithm after each of the four passes over the edges. after making |V|-1 passes, lines 5-8 check for a negative-weight cycle and return the appropriate Boolean value. (We'll see a little later why this check works .)
(You can click an image to enlarge it)
Figure 24.4: the execution of the Bellman-Ford algorithm. The source is vertexS.DValues are shown within the vertices, and shaded edges indicate predecessor values: If edge (U, V) Is shaded, then π [V] =U. In this particle example, each pass relaxes the edges in the order (T, x),(T, y),(T, Z),(X, t),(Y, X),(Y, z),(Z, X),(Z, S),(S, T),(S, y). (A) The situation just before the first pass over the edges. (B)-(e) the situation after each successive pass over the edges.DAnd π values in part (e) are the final values. The Bellman-Ford algorithm returns true in this example.
The bellman-Ford algorithm runs in timeO(V E), Since the initialization in line 1 takes evaluate (V) Time, each of the |V|-1 passes over the edges in lines 2-4 takes sums (E) Time, andForLoop of lines 5-7 takesO(E) Time.
Below isBellman-Ford code:
/*
* About: Bellman-Ford Algorithm
* Author: tanky Woo
* Blog: www.wutianqi.com
*/
# Include <iostream>
Using namespace STD;
Const int maxnum= 100;
Const int maxint= 99999;
// Edge,
Typedef struct edge {
Int U, V; // start point, key
Int weight; // Edge Weight
} Edge;
Edge edge [maxnum]; // Save the edge Value
Int Dist [maxnum]; // minimum distance from a node to a source point
Int nodenum, edgenum, source; // Number of knots, number of edgenum, Source Vertex
// Initialization Diagram
Void Init ()
{
// Enter the number of knots, edges, and source points.
Cin> nodenum> edgenum> source;
For (INT I = 1; I <= nodenum; ++ I)
Dist [I] = maxint;
Dist [Source] = 0;
For (INT I = 1; I <= edgenum; ++ I)
{
Cin> edge [I]. U> edge [I]. V> edge [I]. weight;
If (edge [I]. U = source) // note that the initial conditions are set here.
Dist [edge [I]. V] = edge [I]. weight;
}
}
// Relaxation Calculation
Void relax (int u, int V, int weight)
{
If (Dist [v]> Dist [u] + weight)
Dist [v] = DIST [u] + weight;
}
Bool bellman_ford ()
{
For (INT I = 1; I <= nodenum-1; ++ I)
For (Int J = 1; j <= edgenum; ++ J)
Relax (edge [J]. U, edge [J]. V, edge [J]. weight );
Bool flag = 1;
// Determine whether a negative loop exists
For (INT I = 1; I <= edgenum; ++ I)
If (Dist [edge [I]. V]> Dist [edge [I]. u] + edge [I]. Weight)
{
Flag = 0;
Break;
}
Return flag;
}
Int main ()
{
// Freopen ("input3.txt", "r", stdin );
Init ();
If (bellman_ford ())
For (INT I = 1; I <= nodenum; I ++)
Cout <Dist [I] <Endl;
Return 0;
}