Prerequisites: Bellman-Ford Algorithm
Given a directed weighted graph with V vertices, E edges and a source vertex S. The task is to find the shortest path from the source vertex to all other vertices in the given graph.
Example:
Input: V = 5, S = 1, arr = {{1, 2, 1}, {2, 3, 7}, {2, 4, -2}, {1, 3, 8}, {1, 4, 9}, {3, 4, 3}, {2, 5, 3}, {4, 5, -3}}
Output:
1, 0
2, 1
3, 8
4, -1
5, -4
Explanation: For the given input, the shortest path from 1 to 1 is 0, 1 to 2 is 1 and so on.
Input: V = 5, S = 1, arr = {{1, 2, -1}, {1, 3, 4}, {2, 3, 3}, {2, 4, 2}, {2, 5, 2}, {4, 3, 5}, {4, 2, 1}, {5, 4, 3}}
Output:
1, 0
2, -1
3, 2
4, 1
5, 1
Approach: The shortest path faster algorithm is based on Bellman-Ford algorithm where every vertex is used to relax its adjacent vertices but in SPF algorithm, a queue of vertices is maintained and a vertex is added to the queue only if that vertex is relaxed. This process repeats until no more vertex can be relaxed.
The following steps can be performed to compute the result:
- Create an array d[] to store the shortest distance of all vertex from the source vertex. Initialize this array by infinity except for d[S] = 0 where S is the source vertex.
- Create a queue Q and push starting source vertex in it.
- while Queue is not empty, do the following for each edge(u, v) in the graph
- If d[v] > d[u] + weight of edge(u, v)
- d[v] = d[u] + weight of edge(u, v)
- If vertex v is not present in Queue, then push the vertex v into the Queue.
Note: The term relaxation means updating the cost of all vertices connected to a vertex v if those costs would be improved by including the path via vertex v. This can be understood better from an analogy between the estimate of the shortest path and the length of a helical tension spring, which is not designed for compression. Initially, the cost of the shortest path is an overestimate, likened to a stretched-out spring. As shorter paths are found, the estimated cost is lowered, and the spring is relaxed. Eventually, the shortest path, if one exists, is found and the spring has been relaxed to its resting length.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector<vector<pair< int , int > >> graph;
void addEdge( int frm, int to, int weight)
{
graph[frm].push_back({ to, weight });
}
void print_distance( int d[], int V)
{
cout << "Vertex \t\t Distance"
<< " from source" << endl;
for ( int i = 1; i <= V; i++) {
cout << i << " " << d[i] << '\n' ;
}
}
void shortestPathFaster( int S, int V)
{
int d[V + 1];
bool inQueue[V + 1] = { false };
for ( int i = 0; i <= V; i++) {
d[i] = INT_MAX;
}
d[S] = 0;
queue< int > q;
q.push(S);
inQueue[S] = true ;
while (!q.empty()) {
int u = q.front();
q.pop();
inQueue[u] = false ;
for ( int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].first;
int weight = graph[u][i].second;
if (d[v] > d[u] + weight) {
d[v] = d[u] + weight;
if (!inQueue[v]) {
q.push(v);
inQueue[v] = true ;
}
}
}
}
print_distance(d, V);
}
int main()
{
int V = 5;
int S = 1;
graph = vector<vector<pair< int , int >>> (V+1);
addEdge(1, 2, 1);
addEdge(2, 3, 7);
addEdge(2, 4, -2);
addEdge(1, 3, 8);
addEdge(1, 4, 9);
addEdge(3, 4, 3);
addEdge(2, 5, 3);
addEdge(4, 5, -3);
shortestPathFaster(S, V);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static class pair
{
int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static Vector<pair > []graph = new Vector[ 100000 ];
static void addEdge( int frm, int to, int weight)
{
graph[frm].add( new pair( to, weight ));
}
static void print_distance( int d[], int V)
{
System.out.print( "Vertex \t\t Distance"
+ " from source" + "\n" );
for ( int i = 1 ; i <= V; i++)
{
System.out.printf( "%d \t\t %d\n" , i, d[i]);
}
}
static void shortestPathFaster( int S, int V)
{
int []d = new int [V + 1 ];
boolean []inQueue = new boolean [V + 1 ];
for ( int i = 0 ; i <= V; i++)
{
d[i] = Integer.MAX_VALUE;
}
d[S] = 0 ;
Queue<Integer> q = new LinkedList<>();
q.add(S);
inQueue[S] = true ;
while (!q.isEmpty())
{
int u = q.peek();
q.remove();
inQueue[u] = false ;
for ( int i = 0 ; i < graph[u].size(); i++)
{
int v = graph[u].get(i).first;
int weight = graph[u].get(i).second;
if (d[v] > d[u] + weight)
{
d[v] = d[u] + weight;
if (!inQueue[v])
{
q.add(v);
inQueue[v] = true ;
}
}
}
}
print_distance(d, V);
}
public static void main(String[] args)
{
int V = 5 ;
int S = 1 ;
for ( int i = 0 ; i < graph.length; i++)
{
graph[i] = new Vector<pair>();
}
addEdge( 1 , 2 , 1 );
addEdge( 2 , 3 , 7 );
addEdge( 2 , 4 , - 2 );
addEdge( 1 , 3 , 8 );
addEdge( 1 , 4 , 9 );
addEdge( 3 , 4 , 3 );
addEdge( 2 , 5 , 3 );
addEdge( 4 , 5 , - 3 );
shortestPathFaster(S, V);
}
}
|
C#
using System;
using System.Collections.Generic;
class GFG
{
class pair
{
public int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static List<pair> []graph = new List<pair>[100000];
static void addEdge( int frm, int to, int weight)
{
graph[frm].Add( new pair( to, weight ));
}
static void print_distance( int []d, int V)
{
Console.Write( "Vertex \t\t Distance"
+ " from source" + "\n" );
for ( int i = 1; i <= V; i++)
{
Console.Write( "{0} \t\t {1}\n" , i, d[i]);
}
}
static void shortestPathFaster( int S, int V)
{
int []d = new int [V + 1];
bool []inQueue = new bool [V + 1];
for ( int i = 0; i <= V; i++)
{
d[i] = int .MaxValue;
}
d[S] = 0;
Queue< int > q = new Queue< int >();
q.Enqueue(S);
inQueue[S] = true ;
while (q.Count!=0)
{
int u = q.Peek();
q.Dequeue();
inQueue[u] = false ;
for ( int i = 0; i < graph[u].Count; i++)
{
int v = graph[u][i].first;
int weight = graph[u][i].second;
if (d[v] > d[u] + weight)
{
d[v] = d[u] + weight;
if (!inQueue[v])
{
q.Enqueue(v);
inQueue[v] = true ;
}
}
}
}
print_distance(d, V);
}
public static void Main(String[] args)
{
int V = 5;
int S = 1;
for ( int i = 0; i < graph.Length; i++)
{
graph[i] = new List<pair>();
}
addEdge(1, 2, 1);
addEdge(2, 3, 7);
addEdge(2, 4, -2);
addEdge(1, 3, 8);
addEdge(1, 4, 9);
addEdge(3, 4, 3);
addEdge(2, 5, 3);
addEdge(4, 5, -3);
shortestPathFaster(S, V);
}
}
|
Python3
from collections import deque
graph = [[] for _ in range ( 100000 )]
def addEdge(frm, to, weight):
graph[frm].append([to, weight])
def print_distance(d, V):
print ( "Vertex" , "\t" , "Distance from source" )
for i in range ( 1 , V + 1 ):
print (i, "\t" ,d[i])
def shortestPathFaster(S, V):
d = [ 10 * * 9 ] * (V + 1 )
inQueue = [ False ] * (V + 1 )
d[S] = 0
q = deque()
q.append(S)
inQueue[S] = True
while ( len (q) > 0 ):
u = q.popleft()
inQueue[u] = False
for i in range ( len (graph[u])):
v = graph[u][i][ 0 ]
weight = graph[u][i][ 1 ]
if (d[v] > d[u] + weight):
d[v] = d[u] + weight
if (inQueue[v] = = False ):
q.append(v)
inQueue[v] = True
print_distance(d, V)
if __name__ = = '__main__' :
V = 5
S = 1
addEdge( 1 , 2 , 1 )
addEdge( 2 , 3 , 7 )
addEdge( 2 , 4 , - 2 )
addEdge( 1 , 3 , 8 )
addEdge( 1 , 4 , 9 )
addEdge( 3 , 4 , 3 )
addEdge( 2 , 5 , 3 )
addEdge( 4 , 5 , - 3 )
shortestPathFaster(S, V)
|
Javascript
<script>
let graph= new Array(100000);
function addEdge(frm,to,weight)
{
graph[frm].push([to, weight ]);
}
function print_distance(d,V)
{
document.write(
"Vertex" , " " , "Distance" + " from source" + "<br>"
);
for (let i = 1; i <= V; i++)
{
document.write( i+ " " +
d[i]+ "<br>" );
}
}
function shortestPathFaster(S,V)
{
let d = new Array(V + 1);
let inQueue = new Array(V + 1);
for (let i = 0; i <= V; i++)
{
d[i] = Number.MAX_VALUE;
}
d[S] = 0;
let q = [];
q.push(S);
inQueue[S] = true ;
while (q.length!=0)
{
let u = q[0];
q.shift();
inQueue[u] = false ;
for (let i = 0; i < graph[u].length; i++)
{
let v = graph[u][i][0];
let weight = graph[u][i][1];
if (d[v] > d[u] + weight)
{
d[v] = d[u] + weight;
if (!inQueue[v])
{
q.push(v);
inQueue[v] = true ;
}
}
}
}
print_distance(d, V);
}
let V = 5;
let S = 1;
for (let i = 0; i < graph.length; i++)
{
graph[i] = [];
}
addEdge(1, 2, 1);
addEdge(2, 3, 7);
addEdge(2, 4, -2);
addEdge(1, 3, 8);
addEdge(1, 4, 9);
addEdge(3, 4, 3);
addEdge(2, 5, 3);
addEdge(4, 5, -3);
shortestPathFaster(S, V);
</script>
|
Output: Vertex Distance from source
1 0
2 1
3 8
4 -1
5 -4
Time Complexity:
Average Time Complexity: O(|E|)
Worstcase Time Complexity: O(|V|.|E|)
Space complexity: O(V),The space complexity is O(V) since we need to store the distances for each vertex in an array.
Note: Bound on average runtime has not been proved yet.
References: Shortest Path Faster Algorithm