I. Introduction to Algorithms
The Floyd algorithm is an algorithm for finding the shortest path in a graph. The Floyd algorithm can be used to solve the shortest path in a forward graph with negative weights compared to a Dijkstra algorithm that cannot have negative weights in the graph (although it cannot contain a negative weight loop). It is an algorithm for solving the shortest path between the midpoint and the point of a graph.
We check for each node x in the graph, for 2 points A and B in the graph, if there is dis (ax) +dis (XB) <dis (AB), then the DIS (AB) =dis (AX) +dis (XB). When all nodes x is traversed, the shortest path of AB is obtained.
So, the core code is simple, where N is the number of vertices, the time complexity is O (n^3)
Note the nesting order of 3 for loops
void Floyd (int N) {int i,j,k;for (k=0;k<n;k++) {for (i=0;i<n;i++) {for (j=0;j<n;j++) {if (Dis[i][k]+dis[k][j] <dis[i][j]) {dis[i][j]=dis[i][k]+dis[k][j];}}}}
Two. Principle of the algorithm
The principle of Floyd algorithm is a kind of dynamic programming idea.
Set Ak(I,J) to indicate the shortest path from the I-point to the J-point index number not greater than K.
The shortest path is obtained, which can be expressed as
for (k=0;k<n;k++)
Then, in turn, A0 (i,j) , A1 (i,j), ..., an (i,j), where A0 (I,j) represents the diagram at the time of initialization
In this process, we must first seek A0 (I,J) to seek A1 (I,J), and then A2 (i,j) ..... So this is a bottom-up design idea, why first ask A0 (I,J) to seek A1 (I,J), and then A2 (i,j) ...
Because the algorithm is running this way.
We can be style= by a k a k-1A SUP style= "FONT-FAMILY:VERDANA,SANS-SERIF; line-height:21px; Orphans:2; Widows:2 ">k
first:
a k (i,j) without dot K , at which point
a k (I,J) =< Span style= "FONT-FAMILY:VERDANA,SANS-SERIF; font-size:14px; line-height:21px ">a K-1 (I,J)
second type:
a k (I,J) after a bit of K , at which point
a k (I,J) =< Span style= "FONT-FAMILY:VERDANA,SANS-SERIF; font-size:14px; line-height:21px ">a K-1 (i,k) +< Span style= "FONT-FAMILY:VERDANA,SANS-SERIF; font-size:14px; line-height:21px ">a K-1 (I,K)
Because after K, so this time the path is divided into 2 parts, part from I to K, the other part is K, to J, because K at this time has been as the beginning or end of the 2-part path, so at this time the shortest path required for this 2 part, is to use Ak-1(i,k) and A k-1(i,k). This is a DP idea.
So in 2 cases, I'm going to end up picking the one with the path broken,
SoAk(i,j) = min (ak-1(i,j), ak-1(i,k) + ak-1(k,j))
This step actually corresponds to the code section:
if (Dis[i][k]+dis[k][j]<dis[i][j]) { dis[i][j]=dis[i][k]+dis[k][j];}
Three: Print path
Use Path[i][j] to record path information.
Suppose we exist path 1→5→7→9, then seek path[1][9]=7 first, then seek path[1][7]=5, then seek path[1][5]=1.
Therefore, the algorithm should be replaced by adding path[i][j]=k, because when the path is updated, the path is in the K point, so record it
void Floyd (int N) {int i,j,k;for (k=0;k<n;k++) {for (i=0;i<n;i++) {for (j=0;j<n;j++) {if (Dis[i][k]+dis[k][j] <dis[i][j]) {dis[i][j]=dis[i][k]+dis[k][j];p ath[i][j]=k;}}}}
PATH[I][J] Initialization code:
At first, we assumed that any 2 points in the graph were connected.
for (i=0;i<n;i++) {for (j=0;j<n;j++) {path[i][j]=i;}}
Four: Source code
The code stores the graph with an adjacency matrix, and the input 1000 indicates that 2 vertices are unreachable (unlimited weights)
#include <iostream> #include <stack>using namespace std; #define MAX 1000int Graph[max][max];int dis[max][ MAX]; #define Infinite 1000int path[max][max];void Floyd (int N) {int i,j,k;for (k=0;k<n;k++) {for (i=0;i<n;i++) {for (j=0;j<n;j++) {if (Dis[i][k]+dis[k][j]<dis[i][j]) {dis[i][j]=dis[i][k]+dis[k][j];p ath[i][j]=k;}}}} void Print_path (int N) {int i,j;for (i=0;i<n;i++) {for (j=0;j<n;j++) {if ((i!=j) &&dis[i][j]!=infinite) { cout<<i+1<< "----" <<j+1<< "Distance:" <<Dis[i][j]<<endl;cout<< "Path:" <<endl;int k=j;stack <int> ph;do{k=path[i][k];p H.push (k);} while (k!=i), Cout<<ph.top () +1;ph.pop (), while (!ph.empty ()) {cout<< "--" <<ph.top () +1;ph.pop ();} cout<< "," <<j+1<<endl;}}} void Main () {int n,i,j;cin>>n;for (i=0;i<n;i++) {for (j=0;j<n;j++) {int g;cin>>g; Graph[i][j]=g;dis[i][j]=g;}} Initialize path for (i=0;i<n;i++) {for (j=0;j<n;j++) {path[i][j]=i;}} Floyd (N);p Rint_path (n); System("pause");
Diagram used for testing:
Test results:
The principle and implementation of Floyd algorithm