Floyd-Warshall ),
The article is not original, reprinted ~~
During the summer vacation, Tom is planning to travel to some cities. Some cities have highways, while some cities do not, for example. In order to save money and facilitate the planning of the journey, Tom hopes to know the shortest distance before the departure of any two cities. There are eight highways in four cities. The number on the highway indicates the length of the highway. Note that these roads are unidirectional. Now we need to request the shortest path between any two cities, that is, to find the shortest path between any two points. This problem is also known as the "multi-source shortest path" problem. Now we need a Data Structure to store graph information. We can still store it with a 4*4 matrix (two-dimensional array e. For example, if the distance between city 1 and City 2 is 2, set the value of e [1] [2] to 2. If City 2 cannot reach City 4, set the value of e [2] [4] to ∞. In addition, it is agreed that the city itself is 0, for example, e [1] [1] is 0, as follows. Now let's go back to the question: how can we find the shortest path between any two points? Through previous learning, we know that we can find the shortest path between two points through deep or breadth-first search. Therefore, if you search for depth or breadth over n2 times, you can obtain the shortest path between any two points. But is there any other way? Let's think about it. Based on our past experience, if we want to shorten the distance between any two points (for example, from vertex A to vertex B), we can only introduce the third point (vertex k ), and through this vertex k transit is a-> k-> B, it is possible to shorten the original distance from vertex a to vertex B. Then the transit vertex k is 1 ~ Which of the n points? Sometimes the transfer is shorter after two or more vertices, that is, a-> k1-> k2b-> or a-> k1-> k2... -> K-> I... -> B. For example, the distance from City 4 to city 3 (4-> 3) e [4] [3] is originally 12. If you only transfer data through city 1 (4-> 1-> 3 ), the distance will be shortened to 11 (e [4] [1] + e [1] [3] = 5 + 6 = 11 ). In fact, between city 1 and City 3, you can transfer data through city 2, reduce the distance between city 1 and City 3 to 5 (e [1] [2] + e [2] [3] = 2 + 3 = 5 ). Therefore, if you transfer data between cities 1 and 2, the distance from City 4 to city 3 will be further shortened to 10. Through this example, we find that each vertex may shorten the distance between the other two vertices. Okay. Now let's generalize this problem. When any two points cannot pass through the third point, the shortest distance between these cities is the initial distance, as shown below.
How can we find the shortest path between any two points that can only pass through vertex 1? You only need to determine whether e [I] [1] + e [1] [j] is smaller than e [I] [j. E [I] [j] indicates the distance from vertex I to vertex j. E [I] [1] + e [1] [j] indicates the sum of the distance from vertex I to vertex 1 and then from vertex 1 to vertex j. Where I is 1 ~ N loop, j is also 1 ~ N loop. The code is implemented as follows.
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][j]>e[i][1]+e[1][j]) e[i][j]=e[i][1]+e[1][j];
The shortest path between any two points is updated:
We found that, when only the first vertex is used for transit, the third vertex can be used for the second vertex (e [3] [2]). the distance from vertex 4 to vertex 2 (e [4] [2]) and from vertex 4 to vertex 3 (e [4] [3]) becomes shorter. Next, we will continue to calculate the shortest distance between any two points when only two vertices 1 and 2 are allowed. What should we do? We need to obtain the shortest path of any two points when only the first vertex is allowed, then, determine whether the distance between vertex I and vertex j can be shorter if it passes through vertex 2. That is, to determine whether e [I] [2] + e [2] [j] is smaller than e [I] [j], the code implementation is as follows:
// After the first vertex for (I = 1; I <= n; I ++) for (j = 1; j <= n; j ++) if (e [I] [j]> e [I] [1] + e [1] [j]) e [I] [j] = e [I] [1] + e [1] [j];
// After vertex 2 for (I = 1; I <= n; I ++) for (j = 1; j <= n; j ++) if (e [I] [j]> e [I] [2] + e [2] [j]) e [I] [j] = e [I] [2] + e [2] [j];
The shortest path between any two points is updated:
It is learned that, in the case that only the transit through vertex 1 is allowed, the transit through vertex 1 and vertex 2 is allowed, the distance between e [1] [3] and e [4] [3] is shorter. Similarly, the shortest distance between any two points can be obtained if only the first, second, and third vertices are allowed to pass through. The shortest path between any two points is updated to allow transit through all vertices. The final shortest path between any two points is: although the entire algorithm process is troublesome, but the code implementation is very simple. The core code is only five elements:
for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
The basic idea of this Code is: In the beginning, it is allowed to transit only through vertex 1, and then only through vertex 1 and vertex 2 ...... 1 ~ All vertices on n are transitioned to find the shortest path between any two points. In a word, the shortest distance from vertex I to vertex j is only the first k.
# Include <stdio. h> int main () {int e [10] [10], k, I, j, n, m, u, v, w; int inf = 99999999; // use inf (short for infinity) to store a positive infinity value we think. // read n and m, and n indicates the number of vertices, m indicates the number of edges scanf ("% d", & n, & m); // initialize for (I = 1; I <= n; I ++) for (j = 1; j <= n; j ++) if (I = j) e [I] [j] = 0; else e [I] [j] = inf; // read edge for (I = 1; I <= m; I ++) {scanf ("% d", & u, & v, & w); e [u] [v] = w ;} // Floyd-Warshall algorithm core statement for (k = 1; k <= n; k ++) for (I = 1; I <= n; I ++) for (j = 1; j <= n; j ++) if (e [I] [j]> e [I] [k] + e [k] [j]) e [I] [j] = e [I] [k] + e [k] [j]; // output the final result for (I = 1; I <= n; I ++) {for (j = 1; j <= n; j ++) {printf ("% 10d ", e [I] [j]);} printf ("\ n");} return 0 ;}Note that the Floyd-Warshall algorithm cannot solve the image with a "negative weight loop" (or "negative weight loop, because there is no shortest path in the diagram with a "negative weight loop. For example, the following figure does not have the shortest path from vertex 1 to vertex 3. Because 1-> 2-> 3-> 1-> 2-> 3->... -> 1-> 2-> 3. For every loop such as 1->-2> 3, the shortest path reduces by 1 and the shortest path never finds the shortest path. In fact, if a graph contains a "negative weight loop", there is no Shortest Path in this figure.