Given a directed weighted graph and two vertices S and D in it, the task is to find the shortest path from S to D with exactly K edges on the path. If no such path exists, print -1.
Examples:
Input: N = 3, K = 2, ed = {{{1, 2}, 5}, {{2, 3}, 3}, {{3, 1}, 4}}, S = 1, D = 3
Output: 8
Explanation: The shortest path with two edges will be 1->2->3Input: N = 3, K = 4, ed = {{{1, 2}, 5}, {{2, 3}, 3}, {{3, 1}, 4}}, S = 1, D = 3
Output: -1
Explanation: No path with edge length 4 exists from node 1 to 3Input: N = 3, K = 5, ed = {{{1, 2}, 5}, {{2, 3}, 3}, {{3, 1}, 4}}, S = 1, D = 3
Output: 20
Explanation: Shortest path will be 1->2->3->1->2->3.
Approach: An O(V^3*K) approach for this problem has already been discussed in the previous article. In this article, an O(E*K) approach is discussed for solving this problem.
The idea is to use dynamic-programming to solve this problem.
Let dp[X][J] be the shortest path from node S to node X using exactly J edges in total. Using this, dp[X][J+1] can be calculated as:
dp[X][J+1] = min(arr[Y][J]+weight[{Y, X}]) for all Y which has an edge from Y to X.
The result for the problem can be computed by following below steps:
- Initialise an array, dis[] with initial value as ‘inf’ except dis[S] as 0.
- For i equals 1 – K, run a loop
- Initialise an array, dis1[] with initial value as ‘inf’.
- For each edge in the graph,
dis1[edge.second] = min(dis1[edge.second], dis[edge.first]+weight(edge))
- If dist[d] in infinity, return -1, else return dist[d].
Below is the implementation of the above approach:
// C++ implementation of the above approach #include <bits/stdc++.h> #define inf 100000000 using namespace std;
// Function to find the smallest path // with exactly K edges double smPath( int s, int d,
vector<pair<pair< int , int >, int > > ed,
int n, int k)
{ // Array to store dp
int dis[n + 1];
// Initialising the array
for ( int i = 0; i <= n; i++)
dis[i] = inf;
dis[s] = 0;
// Loop to solve DP
for ( int i = 0; i < k; i++) {
// Initialising next state
int dis1[n + 1];
for ( int j = 0; j <= n; j++)
dis1[j] = inf;
// Recurrence relation
for ( auto it : ed)
dis1[it.first.second] = min(dis1[it.first.second],
dis[it.first.first]
+ it.second);
for ( int i = 0; i <= n; i++)
dis[i] = dis1[i];
}
// Returning final answer
if (dis[d] == inf)
return -1;
else
return dis[d];
} // Driver code int main()
{ int n = 4;
vector<pair<pair< int , int >, int > > ed;
// Input edges
ed = { { { 0, 1 }, 10 },
{ { 0, 2 }, 3 },
{ { 0, 3 }, 2 },
{ { 1, 3 }, 7 },
{ { 2, 3 }, 7 } };
// Source and Destination
int s = 0, d = 3;
// Number of edges in path
int k = 2;
// Calling the function
cout << smPath(s, d, ed, n, k);
} |
// Java implementation of the above approach import java.util.ArrayList;
import java.util.Arrays;
class GFG{
static class Pair<K, V>
{ K first;
V second;
public Pair(K first, V second)
{
this .first = first;
this .second = second;
}
} static int inf = 100000000 ;
// Function to find the smallest path // with exactly K edges static int smPath( int s, int d,
ArrayList<Pair<Pair<Integer, Integer>, Integer>> ed,
int n, int k)
{ // Array to store dp
int [] dis = new int [n + 1 ];
// Initialising the array
Arrays.fill(dis, inf);
dis[s] = 0 ;
// Loop to solve DP
for ( int i = 0 ; i < k; i++)
{
// Initialising next state
int [] dis1 = new int [n + 1 ];
Arrays.fill(dis1, inf);
// Recurrence relation
for (Pair<Pair<Integer, Integer>, Integer> it : ed)
dis1[it.first.second] = Math.min(dis1[it.first.second],
dis[it.first.first] +
it.second);
for ( int j = 0 ; j <= n; j++)
dis[j] = dis1[j];
}
// Returning final answer
if (dis[d] == inf)
return - 1 ;
else
return dis[d];
} // Driver code public static void main(String[] args)
{ int n = 4 ;
// Input edges
ArrayList<Pair<Pair<Integer, Integer>, Integer>> ed = new ArrayList<>(
Arrays.asList(
new Pair<Pair<Integer, Integer>, Integer>(
new Pair<Integer, Integer>( 0 , 1 ), 10 ),
new Pair<Pair<Integer, Integer>, Integer>(
new Pair<Integer, Integer>( 0 , 2 ), 3 ),
new Pair<Pair<Integer, Integer>, Integer>(
new Pair<Integer, Integer>( 0 , 3 ), 2 ),
new Pair<Pair<Integer, Integer>, Integer>(
new Pair<Integer, Integer>( 1 , 3 ), 7 ),
new Pair<Pair<Integer, Integer>, Integer>(
new Pair<Integer, Integer>( 2 , 3 ), 7 )
)
);
// Source and Destination
int s = 0 , d = 3 ;
// Number of edges in path
int k = 2 ;
// Calling the function
System.out.println(smPath(s, d, ed, n, k));
} } // This code is contributed by sanjeev2552 |
# Python3 implementation of the above approach inf = 100000000
# Function to find the smallest path # with exactly K edges def smPath(s, d, ed, n, k):
# Array to store dp
dis = [inf] * (n + 1 )
dis[s] = 0
# Loop to solve DP
for i in range (k):
# Initialising next state
dis1 = [inf] * (n + 1 )
# Recurrence relation
for it in ed:
dis1[it[ 1 ]] = min (dis1[it[ 1 ]],
dis[it[ 0 ]] + it[ 2 ])
for i in range (n + 1 ):
dis[i] = dis1[i]
# Returning final answer
if (dis[d] = = inf):
return - 1
else :
return dis[d]
# Driver code if __name__ = = '__main__' :
n = 4
# Input edges
ed = [ [ 0 , 1 , 10 ],
[ 0 , 2 , 3 ],
[ 0 , 3 , 2 ],
[ 1 , 3 , 7 ],
[ 2 , 3 , 7 ] ]
# Source and Destination
s = 0
d = 3
# Number of edges in path
k = 2
# Calling the function
print (smPath(s, d, ed, n, k))
# This code is contributed by mohit kumar 29 |
// C# implementation of the above approach using System;
using System.Linq;
using System.Collections.Generic;
public class GFG{
static int inf = 100000000;
// Function to find the smallest path // with exactly K edges public static int smPath( int s, int d,
List<KeyValuePair<KeyValuePair< int , int >, int >> ed,
int n, int k)
{ // Array to store dp
// Initialising the array
int []dis = Enumerable.Repeat(inf, n+1).ToArray();
dis[s] = 0;
// Loop to solve DP
for ( int i = 0; i < k; i++)
{
// Initialising next state
int []dis1 = Enumerable.Repeat(inf, n+1).ToArray();
// Recurrence relation
foreach (KeyValuePair<KeyValuePair< int , int >, int > it in ed)
dis1[it.Key.Value] = Math.Min(dis1[it.Key.Value],
dis[it.Key.Key] +
it.Value);
for ( int j = 0; j <= n; j++)
dis[j] = dis1[j];
}
// Returning final answer
if (dis[d] == inf)
return -1;
else
return dis[d];
} // Driver code public static void Main( string [] args)
{ int n = 4;
// Input edges
List<KeyValuePair<KeyValuePair< int , int >, int >> ed = new List<KeyValuePair<KeyValuePair< int , int >, int >>(){
new KeyValuePair<KeyValuePair< int , int >, int >(
new KeyValuePair< int , int >(0, 1), 10),
new KeyValuePair<KeyValuePair< int , int >, int >(
new KeyValuePair< int , int >(0, 2), 3),
new KeyValuePair<KeyValuePair< int , int >, int >(
new KeyValuePair< int , int >(0, 3), 2),
new KeyValuePair<KeyValuePair< int , int >, int >(
new KeyValuePair< int , int >(1, 3), 7),
new KeyValuePair<KeyValuePair< int , int >, int >(
new KeyValuePair< int , int >(2, 3), 7)
};
// Source and Destination
int s = 0, d = 3;
// Number of edges in path
int k = 2;
// Calling the function
Console.Write(smPath(s, d, ed, n, k));
} } // This code is contributed by rrrtnx. |
<script> // Javascript implementation of the above approach let inf = 100000000; // Function to find the smallest path // with exactly K edges function smPath(s,d,ed,n,k)
{ // Array to store dp
let dis = new Array(n + 1);
// Initialising the array
for (let i=0;i<(n+1);i++)
{
dis[i]=inf;
}
dis[s] = 0;
// Loop to solve DP
for (let i = 0; i < k; i++)
{
// Initialising next state
let dis1 = new Array(n + 1);
for (let i=0;i<(n+1);i++)
{
dis1[i]=inf;
}
// Recurrence relation
for (let it=0;it< ed.length;it++)
dis1[ed[it][1]] = Math.min(dis1[ed[it][1]],
dis[ed[it][0]] +
ed[it][2]);
document.write()
for (let j = 0; j <= n; j++)
dis[j] = dis1[j];
}
// Returning final answer
if (dis[d] == inf)
return -1;
else
return dis[d];
} // Driver code let n = 4; // Input edges
let ed = [ [0, 1 ,10], [ 0, 2 ,3],
[ 0, 3 ,2],
[ 1, 3 ,7],
[ 2, 3 ,7] ];
// Source and Destination let s = 0, d = 3; // Number of edges in path let k = 2; // Calling the function document.write(smPath(s, d, ed, n, k)); // This code is contributed by patel2127 </script> |
10
Time complexity: O(E*K)
Space complexity: O(N)