Shortest path with exactly k edges in a directed and weighted graph
Last Updated :
31 Jan, 2023
Given a directed and two vertices ‘u’ and ‘v’ in it, find shortest path from ‘u’ to ‘v’ with exactly k edges on the path.
The graph is given as adjacency matrix representation where value of graph[i][j] indicates the weight of an edge from vertex i to vertex j and a value INF(infinite) indicates no edge from i to j.
For example, consider the following graph. Let source ‘u’ be vertex 0, destination ‘v’ be 3 and k be 2. There are two walks of length 2, the walks are {0, 2, 3} and {0, 1, 3}. The shortest among the two is {0, 2, 3} and weight of path is 3+6 = 9.
The idea is to browse through all paths of length k from u to v using the approach discussed in the previous post and return weight of the shortest path. A simple solution is to start from u, go to all adjacent vertices, and recur for adjacent vertices with k as k-1, source as adjacent vertex and destination as v. Following are C++ and Java implementations of this simple solution.
C++
#include <bits/stdc++.h>
using namespace std;
#define V 4
#define INF INT_MAX
int shortestPath( int graph[][V], int u, int v, int k)
{
if (k == 0 && u == v) return 0;
if (k == 1 && graph[u][v] != INF) return graph[u][v];
if (k <= 0) return INF;
int res = INF;
for ( int i = 0; i < V; i++)
{
if (graph[u][i] != INF && u != i && v != i)
{
int rec_res = shortestPath(graph, i, v, k-1);
if (rec_res != INF)
res = min(res, graph[u][i] + rec_res);
}
}
return res;
}
int main()
{
int graph[V][V] = { {0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0}
};
int u = 0, v = 3, k = 2;
cout << "Weight of the shortest path is " <<
shortestPath(graph, u, v, k);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
import java.io.*;
class ShortestPath
{
static final int V = 4 ;
static final int INF = Integer.MAX_VALUE;
int shortestPath( int graph[][], int u, int v, int k)
{
if (k == 0 && u == v) return 0 ;
if (k == 1 && graph[u][v] != INF) return graph[u][v];
if (k <= 0 ) return INF;
int res = INF;
for ( int i = 0 ; i < V; i++)
{
if (graph[u][i] != INF && u != i && v != i)
{
int rec_res = shortestPath(graph, i, v, k- 1 );
if (rec_res != INF)
res = Math.min(res, graph[u][i] + rec_res);
}
}
return res;
}
public static void main (String[] args)
{
int graph[][] = new int [][]{ { 0 , 10 , 3 , 2 },
{INF, 0 , INF, 7 },
{INF, INF, 0 , 6 },
{INF, INF, INF, 0 }
};
ShortestPath t = new ShortestPath();
int u = 0 , v = 3 , k = 2 ;
System.out.println( "Weight of the shortest path is " +
t.shortestPath(graph, u, v, k));
}
}
|
Python3
def shortestPath(graph, u, v, k):
V = 4
INF = 999999999999
if k = = 0 and u = = v:
return 0
if k = = 1 and graph[u][v] ! = INF:
return graph[u][v]
if k < = 0 :
return INF
res = INF
for i in range (V):
if graph[u][i] ! = INF and u ! = i and v ! = i:
rec_res = shortestPath(graph, i, v, k - 1 )
if rec_res ! = INF:
res = min (res, graph[u][i] + rec_res)
return res
if __name__ = = '__main__' :
INF = 999999999999
graph = [[ 0 , 10 , 3 , 2 ],
[INF, 0 , INF, 7 ],
[INF, INF, 0 , 6 ],
[INF, INF, INF, 0 ]]
u = 0
v = 3
k = 2
print ( "Weight of the shortest path is" ,
shortestPath(graph, u, v, k))
|
C#
using System;
class GFG
{
const int V = 4;
const int INF = Int32.MaxValue;
int shortestPath( int [,] graph, int u,
int v, int k)
{
if (k == 0 && u == v) return 0;
if (k == 1 && graph[u, v] != INF) return graph[u, v];
if (k <= 0) return INF;
int res = INF;
for ( int i = 0; i < V; i++)
{
if (graph[u, i] != INF && u != i && v != i)
{
int rec_res = shortestPath(graph, i, v, k - 1);
if (rec_res != INF)
res = Math.Min(res, graph[u, i] + rec_res);
}
}
return res;
}
public static void Main ()
{
int [,] graph = new int [,]{{0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0}};
GFG t = new GFG();
int u = 0, v = 3, k = 2;
Console.WriteLine( "Weight of the shortest path is " +
t.shortestPath(graph, u, v, k));
}
}
|
Javascript
<script>
let V = 4;
let INF = Number.MAX_VALUE;
function shortestPath(graph,u,v,k)
{
if (k == 0 && u == v) return 0;
if (k == 1 && graph[u][v] != INF) return graph[u][v];
if (k <= 0) return INF;
let res = INF;
for (let i = 0; i < V; i++)
{
if (graph[u][i] != INF && u != i && v != i)
{
let rec_res = shortestPath(graph, i, v, k-1);
if (rec_res != INF)
res = Math.min(res, graph[u][i] + rec_res);
}
}
return res;
}
let graph=[[0, 10, 3, 2],[INF, 0, INF, 7],
[INF, INF, 0, 6],[INF, INF, INF, 0]];
let u = 0, v = 3, k = 2;
document.write( "Weight of the shortest path is " +
shortestPath(graph, u, v, k));
</script>
|
Output
Weight of the shortest path is 9
Time Complexity: O(VK)
Space Complexity: O(V)
The worst-case time complexity of the above function is O(Vk) where V is the number of vertices in the given graph. We can simply analyze the time complexity by drawing recursion tree. The worst occurs for a complete graph. In worst case, every internal node of recursion tree would have exactly V children.
We can optimize the above solution using Dynamic Programming. The idea is to build a 3D table where first dimension is source, second dimension is destination, third dimension is number of edges from source to destination, and the value is the weight of the shortest path having exactly the number of edges, stored in the third dimension, from source to destination. Like other Dynamic Programming problems, we fill the 3D table in bottom-up manner.
C++
#include <iostream>
#include <climits>
using namespace std;
#define V 4
#define INF INT_MAX
int shortestPath( int graph[][V], int u, int v, int k)
{
int sp[V][V][k+1];
for ( int e = 0; e <= k; e++)
{
for ( int i = 0; i < V; i++)
{
for ( int j = 0; j < V; j++)
{
sp[i][j][e] = INF;
if (e == 0 && i == j)
sp[i][j][e] = 0;
if (e == 1 && graph[i][j] != INF)
sp[i][j][e] = graph[i][j];
if (e > 1)
{
for ( int a = 0; a < V; a++)
{
if (graph[i][a] != INF && i != a &&
j!= a && sp[a][j][e-1] != INF)
sp[i][j][e] = min(sp[i][j][e], graph[i][a] +
sp[a][j][e-1]);
}
}
}
}
}
return sp[u][v][k];
}
int main()
{
int graph[V][V] = { {0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0}
};
int u = 0, v = 3, k = 2;
cout << shortestPath(graph, u, v, k);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
import java.io.*;
class ShortestPath
{
static final int V = 4 ;
static final int INF = Integer.MAX_VALUE;
int shortestPath( int graph[][], int u, int v, int k)
{
int sp[][][] = new int [V][V][k+ 1 ];
for ( int e = 0 ; e <= k; e++)
{
for ( int i = 0 ; i < V; i++)
{
for ( int j = 0 ; j < V; j++)
{
sp[i][j][e] = INF;
if (e == 0 && i == j)
sp[i][j][e] = 0 ;
if (e == 1 && graph[i][j] != INF)
sp[i][j][e] = graph[i][j];
if (e > 1 )
{
for ( int a = 0 ; a < V; a++)
{
if (graph[i][a] != INF && i != a &&
j!= a && sp[a][j][e- 1 ] != INF)
sp[i][j][e] = Math.min(sp[i][j][e],
graph[i][a] + sp[a][j][e- 1 ]);
}
}
}
}
}
return sp[u][v][k];
}
public static void main (String[] args)
{
int graph[][] = new int [][]{ { 0 , 10 , 3 , 2 },
{INF, 0 , INF, 7 },
{INF, INF, 0 , 6 },
{INF, INF, INF, 0 }
};
ShortestPath t = new ShortestPath();
int u = 0 , v = 3 , k = 2 ;
System.out.println( "Weight of the shortest path is " +
t.shortestPath(graph, u, v, k));
}
}
|
Python3
def shortestPath(graph, u, v, k):
global V, INF
sp = [[ None ] * V for i in range (V)]
for i in range (V):
for j in range (V):
sp[i][j] = [ None ] * (k + 1 )
for e in range (k + 1 ):
for i in range (V):
for j in range (V):
sp[i][j][e] = INF
if (e = = 0 and i = = j):
sp[i][j][e] = 0
if (e = = 1 and graph[i][j] ! = INF):
sp[i][j][e] = graph[i][j]
if (e > 1 ):
for a in range (V):
if (graph[i][a] ! = INF and i ! = a and
j! = a and sp[a][j][e - 1 ] ! = INF):
sp[i][j][e] = min (sp[i][j][e], graph[i][a] +
sp[a][j][e - 1 ])
return sp[u][v][k]
V = 4
INF = 999999999999
graph = [[ 0 , 10 , 3 , 2 ],
[INF, 0 , INF, 7 ],
[INF, INF, 0 , 6 ],
[INF, INF, INF, 0 ]]
u = 0
v = 3
k = 2
print ( "Weight of the shortest path is" ,
shortestPath(graph, u, v, k))
|
C#
using System;
class GFG
{
static readonly int V = 4;
static readonly int INF = int .MaxValue;
int shortestPath( int [,]graph, int u, int v, int k)
{
int [,,]sp = new int [V, V, k + 1];
for ( int e = 0; e <= k; e++)
{
for ( int i = 0; i < V; i++)
{
for ( int j = 0; j < V; j++)
{
sp[i, j, e] = INF;
if (e == 0 && i == j)
sp[i, j, e] = 0;
if (e == 1 && graph[i, j] != INF)
sp[i, j, e] = graph[i, j];
if (e > 1)
{
for ( int a = 0; a < V; a++)
{
if (graph[i, a] != INF && i != a &&
j!= a && sp[a, j, e - 1] != INF)
sp[i, j, e] = Math.Min(sp[i, j, e],
graph[i, a] + sp[a, j, e - 1]);
}
}
}
}
}
return sp[u, v, k];
}
public static void Main(String[] args)
{
int [,]graph = new int [,]{ {0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0} };
GFG t = new GFG();
int u = 0, v = 3, k = 2;
Console.WriteLine( "Weight of the shortest path is " +
t.shortestPath(graph, u, v, k));
}
}
|
Javascript
<script>
let V = 4;
let INF = Number.MAX_VALUE;
function shortestPath(graph, u, v, k)
{
let sp = new Array(V);
for (let i = 0; i < V; i++)
{
sp[i] = new Array(V);
for (let j = 0; j < V; j++)
{
sp[i][j] = new Array(k + 1);
for (let l = 0; l < (k + 1); l++)
{
sp[i][j][l] = 0;
}
}
}
for (let e = 0; e <= k; e++)
{
for (let i = 0; i < V; i++)
{
for (let j = 0; j < V; j++)
{
sp[i][j][e] = INF;
if (e == 0 && i == j)
sp[i][j][e] = 0;
if (e == 1 && graph[i][j] != INF)
sp[i][j][e] = graph[i][j];
if (e > 1)
{
for (let a = 0; a < V; a++)
{
if (graph[i][a] != INF && i != a &&
j!= a && sp[a][j][e-1] != INF)
sp[i][j][e] = Math.min(sp[i][j][e],
graph[i][a] + sp[a][j][e-1]);
}
}
}
}
}
return sp[u][v][k];
}
let graph = [[0, 10, 3, 2], [INF, 0, INF, 7], [INF, INF, 0, 6], [INF, INF, INF, 0]];
let u = 0, v = 3, k = 2;
document.write( "Weight of the shortest path is " +
shortestPath(graph, u, v, k));
</script>
|
Time complexity of the above DP-based solution is O(V3K) which is much better than the naive solution.
Auxiliary Space: O(V2K) as we are required to store DP states.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...