mirror of
https://github.com/dholerobin/Lecture_Notes.git
synced 2025-07-01 04:56:29 +00:00
Create Floyd-Warshall.md
This commit is contained in:
parent
1ffbb05884
commit
901afd148a
291
Akash Articles/Floyd-Warshall.md
Normal file
291
Akash Articles/Floyd-Warshall.md
Normal file
@ -0,0 +1,291 @@
|
||||
## All Pair Shortest Path Problem
|
||||
|
||||
Statement: Given a graph, Find out the shortest distance paths between every pair of vertices.
|
||||
|
||||
## Brute Force
|
||||
|
||||
We have seen Dijkstra's algorithm and Bellman-Ford algorithm, which solves the SSSP problem.
|
||||
|
||||
We can run these algorithms for every vertex one by one, which solves the given problem.
|
||||
|
||||
This will give the complexity of $\mathcal{O}( (|V| + |E|) \cdot |V| \cdot log|V|)$ in the case of Dijkstra's algorithm and $\mathcal{O} (|V|^2 \cdot |E|)$ in the case of Bellman-Ford Algorithm.
|
||||
|
||||
**Floyd-Warshall Algorithm** solves all pair shortest path problem in an efficient manner.
|
||||
|
||||
## Floyd-Warshall Algorithm
|
||||
|
||||
This algorithm is an example of Dynamic Programming. We split the process of finding the shortest paths in several phases.
|
||||
|
||||
-- --
|
||||
|
||||
### Quiz Time
|
||||
|
||||
You are given that the shortest path between two vertices $A$ and $B$ passes through $C$, i.e. $C$ is the intermediate vertex in the shortest path from $A$ to $B$. What can you conclude from it?
|
||||
|
||||
Answer: $SD(A, B) = SD(A,C) + SD(C,B)$
|
||||
|
||||
$SD$ stands for Shortest Distance.
|
||||
|
||||
-- --
|
||||
|
||||
The above answer can be proved using contradiction.
|
||||
|
||||
The Floyd-Warshall algorithm works based on the above answer.
|
||||
|
||||
Before the $i^{th}$ phase of the algorithm, it finds out the shortest distance path between every pair of vertices which uses intermediate vertices only from the set $\{1,2,..,i-1\}$. In every phase of the algorithm, we add one more vertex in the set.
|
||||
|
||||
In the $i^{th}$ phase, we update the $distance$ matrix considering the two cases below:
|
||||
|
||||
For an entry $distance[a][b]$,
|
||||
|
||||
1. If the shortest path between $a$ and $b$ which uses intermediate vertices from the set $\{1,2,...i-1\}$ is longer than the one that uses $\{1,2,...,i\}$, then update the shortest distance path as below:
|
||||
|
||||
$distance[a][b] = distance[a][i]+distance[i][b]$
|
||||
|
||||
Where $distance[a][b]$ is the shortest distance between $a$ and $b$ which uses intermediate vertices from the set $\{1,2,..,i-1\}$.
|
||||
|
||||
2. Otherwise, $distance[a][b]$ will remain unchanged.
|
||||
|
||||
### Algorithm
|
||||
|
||||
1. Initialize $N \times N$ distance matrix with infinity.
|
||||
2. Assign every element representing distance between vertex to itself to zero - assign every diagonal element of distance matrix to zero.
|
||||
3. For all pair of vertices, If there is an edge between $A$ and $B$, then update $distance[A][B]$ to $Edge Weight(A,B)$.
|
||||
4. Start from the first vertex, say phase $i=1$.
|
||||
5. For all pairs of the vertices, update the new shortest distance between them using the condition below,
|
||||
$distance[a][b] > distance[a][i]+distance[i][b]$
|
||||
6. If $i$ is equal to the number of vertices, then stop otherwise increment $i$ and repeat step $5$.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Floyd_Warshall(int no_vertices, vector<vector<int> > & distances)
|
||||
{
|
||||
// i shows the phase
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
{
|
||||
// Update distance matrix for all pairs
|
||||
for(int a = 1; a <= no_vertices; a++)
|
||||
{
|
||||
for(int b = 1; b <= no_vertices; b++)
|
||||
{
|
||||
if(distances[a][i] < MAX_DIST && distances[i][b] < MAX_DIST)
|
||||
distances[a][b] = min(distances[a][b], distances[a][i]+distances[i][b]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// N*N array to store the distances between every pair
|
||||
vector<vector<int> > distances(no_vertices+1, vector<int> (no_vertices+1, MAX_DIST));
|
||||
|
||||
// Adding the edges virtually by
|
||||
// updating distance matrix
|
||||
distances[1][2]=1;
|
||||
distances[1][3]=-3;
|
||||
distances[2][4]=2;
|
||||
distances[2][5]=1;
|
||||
distances[3][4]=-1;
|
||||
distances[3][5]=2;
|
||||
distances[4][5]=1;
|
||||
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
distances[i][i] = 0;
|
||||
|
||||
Floyd_Warshall(no_vertices, distances);
|
||||
|
||||
// Printing the distance matrix
|
||||
for(int i=1;i<=no_vertices;i++)
|
||||
{
|
||||
for(int j=1;j<=no_vertices;j++)
|
||||
{
|
||||
if(distances[i][j]!=MAX_DIST)
|
||||
cout << setw(5) << right << distances[i][j] << " ";
|
||||
else
|
||||
cout << setw(5) << right << "INF" << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Time Complexity
|
||||
As there are three loops, each running number of vertices time, the complexity will be $\mathcal{O}(|V|^3)$.
|
||||
|
||||
In worst case, this is better than the brute force approach.
|
||||
|
||||
### Path Reconstruction
|
||||
|
||||
To reconstruct the path, we have to store the next vertex for each pair and whenever we update the shortest distance we have to update the next vertex as well.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Floyd_Warshall(int no_vertices, vector<vector<int> > & distances, vector<vector<int> > & next)
|
||||
{
|
||||
// i shows the phase
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
{
|
||||
// Update distance matrix for all pairs
|
||||
for(int a = 1; a <= no_vertices; a++)
|
||||
for(int b = 1; b <= no_vertices; b++)
|
||||
if( distances[a][b] > distances[a][i]+distances[i][b] &&
|
||||
distances[a][i] < MAX_DIST && distances[i][b] < MAX_DIST )
|
||||
{
|
||||
distances[a][b] = distances[a][i]+distances[i][b];
|
||||
next[a][b] = next[a][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// N*N array to store the distances between every pair
|
||||
vector<vector<int> > distances(no_vertices+1, vector<int> (no_vertices+1, MAX_DIST));
|
||||
|
||||
|
||||
// N*N array to store the next vertex for every pair
|
||||
vector<vector<int> > next(no_vertices+1, vector<int> (no_vertices+1, -1));
|
||||
|
||||
|
||||
// Adding the edges virtually by
|
||||
// updating distance matrix and
|
||||
// next vertex matrix
|
||||
distances[1][2]=1, next[1][2] = 2;
|
||||
distances[1][3]=-3, next[1][3] = 3;
|
||||
distances[2][4]=2, next[2][4] = 4;
|
||||
distances[2][5]=1, next[2][5] = 5;
|
||||
distances[3][4]=-1, next[3][4] = 4;
|
||||
distances[3][5]=2, next[3][5] = 5;
|
||||
distances[4][5]=1, next[4][5] = 5;
|
||||
|
||||
// Update all the diagonal elements
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
{
|
||||
distances[i][i] = 0;
|
||||
next[i][i] = i;
|
||||
}
|
||||
|
||||
Floyd_Warshall(no_vertices, distances, next);
|
||||
|
||||
// Example of path reconstruction
|
||||
int source = 1, destination = 5;
|
||||
|
||||
while(source != destination)
|
||||
{
|
||||
cout << source << " ";
|
||||
source = next[source][destination];
|
||||
}
|
||||
|
||||
cout << destination << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Negative Cycle Case
|
||||
|
||||
We can use the Floyd-Warshall algorithm to detect the negative cycle and to find the pair of vertices affected by it.
|
||||
|
||||
Initially, the distance between the vertex to itself was zero, but if it turns out to be negative at the end of the algorithm, then there is a negative cycle.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Floyd_Warshall_with_NC(int no_vertices, vector<vector<int> > & distances)
|
||||
{
|
||||
// i shows the phase
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
for(int a = 1; a <= no_vertices; a++)
|
||||
for(int b = 1; b <= no_vertices; b++)
|
||||
if( distances[a][b] > distances[a][i]+distances[i][b] &&
|
||||
distances[a][i] < MAX_DIST && distances[i][b] < MAX_DIST )
|
||||
distances[a][b] = distances[a][i]+distances[i][b];
|
||||
|
||||
|
||||
bool is_negative_cycle = false;
|
||||
|
||||
// Check for negative cycle
|
||||
for (int i = 1; i <= no_vertices; ++i)
|
||||
for (int a = 1; a <= no_vertices; ++a)
|
||||
for (int b = 1; b <= no_vertices; ++b)
|
||||
{
|
||||
// If there is a negative cycle, then update the distance to -Infinity
|
||||
if (distances[a][i] < MAX_DIST && distances[i][i] < 0
|
||||
&& distances[i][b] < MAX_DIST)
|
||||
{
|
||||
distances[a][b] = -MAX_DIST;
|
||||
is_negative_cycle = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(is_negative_cycle)
|
||||
{
|
||||
cout << "The following pairs are affected by the negative cycle:" << endl;
|
||||
for (int a = 1; a <= no_vertices; ++a)
|
||||
for (int b = 1; b <= no_vertices; ++b)
|
||||
if (distances[a][b] = -MAX_DIST)
|
||||
cout << a << "--" << b << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int no_vertices=5;
|
||||
|
||||
// N*N array to store the distances between every pair
|
||||
vector<vector<int> > distances(no_vertices+1, vector<int> (no_vertices+1, MAX_DIST));
|
||||
|
||||
|
||||
// Adding the edges virtually by
|
||||
// updating distance matrix
|
||||
distances[1][2]=1;
|
||||
distances[1][3]=-3;
|
||||
distances[2][4]=2;
|
||||
distances[4][1]=1;
|
||||
distances[3][4]=-2;
|
||||
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
distances[i][i] = 0;
|
||||
|
||||
Floyd_Warshall_with_NC(no_vertices, distances);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Application of Floyd-Warshall Algorithm
|
||||
|
||||
1. "Widest Path Finding Algorithm", which is an algorithm to finding a path between two vertices of the graph **maximizing the weight of the minimum-weight edge in the path**, can be solved using this algorithm.
|
||||
2. To do optimal routing.
|
||||
3. In Gauss-Jordan Algorithm, to find reduced form of matrix and inversion matrix.
|
||||
|
||||
## Other Shortest Path Finding Algorithms:
|
||||
|
||||
1. Using Dynamic Programming
|
||||
2. Dijkstra's Algorithm
|
||||
3. Bellman-Ford Algorithm
|
Loading…
x
Reference in New Issue
Block a user