Shortest path in a graph from a source S to destination D with exactly K edges for multiple Queries

13 May, 2021
Given a graph with N nodes, a node S and Q queries each consisting of a node D and K, the task is to find the shortest path consisting of exactly K edges from node S to node D for each query. If no such path exists then print -1. 
Note: K will always be lesser than 2 * N.
Examples: 
Input: N = 3, edges[][] = {{1, 2, 5}, {2, 3, 3}, {3, 1, 4}}, S = 1, Q = {{1, 0}, {2, 1}, {3, 1}, {3, 2}, {3, 5}} Output: 0 5 -1 8 20 1. The shortest path from 1 to 1 using 0 edge will be 0. 2. The shortest path from 1 to 2 using 1 edge will be 5 i.e 1->2. 3. No path of 1 edge exists between nodes 1 and 3. 4. The shortest path from 1 to 3 using 2 edges will be 8 i.e 1->2->3. 5. The shortest path from 1 to 3 using 5 edges will be 20 i.e 1->2->3->1->2->3.
Input: N = 4, edges[][] = {{1, 2, 8}, {2, 3, 5}, {3, 4, 7}}, S = 1, Q = {{1, 0}, {2, 1}, {3, 1}, {3, 2}, {4, 5}} Output: 0 8 -1 13 -1  
Approach:  
This problem can be solved with the help of dynamic programming to create a linear solution.
Initialize a 2-d array, dp[N][2*N] with initial value as ‘inf’ except dp[S][0] as 0.
Pre-process the graph to find the shortest distance of each and every node from the source for every edge length between {0 to N-1}. The array dp[][] will be used to store the results of the pre-processing.
For the pre-processing, run a loop for J in the range [1, 2*N-1] to find the dp[X][J] for each edge in the graph, where dp[X][J] be the shortest path from node ‘S’ to node ‘X’ using exactly ‘J’ edges in total.
We can find dp[X][J+1] with the help of a recurrence relation:
dp[ edge.second ][ i ] = min(dp[ edge.second ][ i ], dp[ edge.first ][ i-1 ] + weight(edge))  
For every query in Q, if(dp[X][k] == inf) then return -1, else return dp[X][k]
Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ implementation of the approach #include <bits/stdc++.h>using namespace std; #define inf 100000000 // Function to find the shortest path// between S and D with exactly K edgesvoid ansQueries(int s,                vector<pair<pair<int, int>, int> > ed,                int n, vector<pair<int, int> > q){     // To store the dp states    int dp[n + 1][2 * n];     // Initialising the dp[][] array    for (int i = 0; i <= n; i++)        dp[i][0] = inf;    dp[s][0] = 0;     // Pre-Processing    for (int i = 1; i <= 2 * n - 1; i++) {         // Initialising current state        for (int j = 0; j <= n; j++)            dp[j][i] = inf;         // Updating current state        for (auto it : ed) {            dp[it.first.second][i]                = min(                    dp[it.first.second][i],                    dp[it.first.first][i - 1] + it.second);        }    }     for (int i = 0; i < q.size(); i++) {        if (dp[q[i].first][q[i].second] == inf)            cout << -1 << endl;        else            cout << dp[q[i].first][q[i].second]                 << endl;    }} // Driver codeint main(){    int n = 3;    vector<pair<pair<int, int>, int> > ed;     // Edges    ed = { { { 1, 2 }, 5 },           { { 2, 3 }, 3 },           { { 3, 1 }, 4 } };     // Source    int s = 1;     // Queries    vector<pair<int, int> > q = { { 1, 0 },                                  { 2, 1 },                                  { 3, 1 },                                  { 3, 2 },                                  { 3, 5 } };     // Function to answer queries    ansQueries(s, ed, n, q);     return 0;}
// Java implementation of the approachimport java.util.*;import java.lang.*;import java.io.*; class GFG{ static int inf = 100000000;   // Function to find the shortest path// between S and D with exactly K edgesstatic void ansQueries(int s,                       int[][] ed,                int n, int[][] q){         // To store the dp states    int[][] dp = new int[n + 1][2 * n];       // Initialising the dp[][] array    for(int i = 0; i <= n; i++)        dp[i][0] = inf;             dp[s][0] = 0;       // Pre-Processing    for(int i = 1; i <= 2 * n - 1; i++)    {                 // Initialising current state        for(int j = 0; j <= n; j++)            dp[j][i] = inf;           // Updating current state        for(int[] it : ed)        {            dp[it[1]][i] = Math.min(dp[it[1]][i],                                    dp[it[0]][i - 1] +                                       it[2]);        }    }       for(int i = 0; i < q.length; i++)    {        if (dp[q[i][0]][q[i][1]] == inf)             System.out.println(-1);         else             System.out.println(dp[q[i][0]][q[i][1]]);    }}   // Driver codepublic static void main(String[] args){    int n = 3;         // Edges    int[][] ed = { { 1, 2, 5 },                   { 2, 3, 3 },                   { 3, 1, 4 } };         // Source    int s = 1;         // Queries    int[][] q = { { 1, 0 },                  { 2, 1 },                  { 3, 1 },                  { 3, 2 },                  { 3, 5 } };         // Function to answer queries    ansQueries(s, ed, n, q);}} // This code is contributed by offbeat
# Python3 implementation of the approachimport sys,numpy as np inf = sys.maxsize; # Function to find the shortest path# between S and D with exactly K edgesdef ansQueries(s, ed, n, q) :     # To store the dp states    dp = np.zeros((n + 1, 2 * n));     # Initialising the dp[][] array    for i in range(n + 1) :        dp[i][0] = inf;             dp[s][0] = 0;     # Pre-Processing    for i in range( 1, 2 * n) :         # Initialising current state        for j in range( n + 1) :            dp[j][i] = inf;         # Updating current state        for it in ed :            dp[it[1]][i] = min( dp[it[1]][i],                                dp[it[0]][i - 1] + ed[it]);         for i in range(len(q)) :        if (dp[q[i][0]][q[i][1]] == inf) :            print(-1);        else :            print(dp[q[i][0]][q[i][1]]); # Driver codeif __name__ == "__main__" :     n = 3;     # Edges    ed = { ( 1, 2 ) : 5 ,        ( 2, 3 ) : 3 ,        ( 3, 1 ) : 4 };     # Source    s = 1;     # Queries    q = [        ( 1, 0 ),        ( 2, 1 ),        ( 3, 1 ),        ( 3, 2 ),        ( 3, 5 )        ];     # Function to answer queries    ansQueries(s, ed, n, q);     # This code is contributed by AnkitRai01
// C# implementation of the approachusing System;class GFG{  static int inf = 100000000;   // Function to find the shortest path  // between S and D with exactly K edges  static void ansQueries(int s, int[][] ed, int n, int[][] q)  {     // To store the dp states    int[, ] dp = new int[n + 1, 2 * n];     // Initialising the dp[][] array    for (int i = 0; i <= n; i++)      dp[i, 0] = inf;    dp[s, 0] = 0;     // Pre-Processing    for (int i = 1; i <= 2 * n - 1; i++)    {             // Initialising current state      for (int j = 0; j <= n; j++)        dp[j, i] = inf;       // Updating current state      foreach (int[] it in ed)      {        dp[it[1], i] = Math.Min(dp[it[1], i],                                dp[it[0], i - 1] + it[2]);      }    }     for (int i = 0; i < q.Length; i++)    {      if (dp[q[i][0], q[i][1]] == inf)        Console.WriteLine(-1);      else        Console.WriteLine(dp[q[i][0], q[i][1]]);    }  }   // Driver code  public static void Main(string[] args)  {    int n = 3;     // Edges    int[][] ed = {      new int[3]{1, 2, 5},      new int[3]{2, 3, 3},      new int[3]{3, 1, 4}    };     // Source    int s = 1;     // Queries    int[][] q = {      new int[2]{1, 0},      new int[2]{2, 1},      new int[2]{3, 1},      new int[2]{3, 2},      new int[2]{3, 5}    };     // Function to answer queries    ansQueries(s, ed, n, q);  }}    // This code is contributed by sanjeev2552
<script> // Javascript implementation of the approachvar inf = 100000000; // Function to find the shortest path// between S and D with exactly K edgesfunction ansQueries( s, ed, n,  q){     // To store the dp states    var dp = Array.from(Array(n+1), ()=> Array(2*n));     // Initialising the dp[][] array    for (var i = 0; i <= n; i++)        dp[i][0] = inf;    dp[s][0] = 0;     // Pre-Processing    for (var i = 1; i <= 2 * n - 1; i++) {         // Initialising current state        for (var j = 0; j <= n; j++)            dp[j][i] = inf;         // Updating current state        for(var it =0; it<ed.length; it++)        {            dp[ed[it][0][1]][i]                = Math.min(                    dp[ed[it][0][1]][i],                    dp[ed[it][0][0]][i - 1] + ed[it][1]);        }    }     for (var i = 0; i < q.length; i++) {        if (dp[q[i][0]][q[i][1]] == inf)            document.write( -1+ "<br>" );        else            document.write( dp[q[i][0]][q[i][1]]+ "<br>");    }} // Driver codevar n = 3;var ed;// Edgesed = [ [ [ 1, 2 ], 5 ],       [ [ 2, 3 ], 3 ],       [ [ 3, 1 ], 4 ] ];// Sourcevar s = 1;// Queriesvar q = [ [ 1, 0 ],                              [ 2, 1 ],                              [ 3, 1 ],                              [ 3, 2 ],                              [ 3, 5 ] ];// Function to answer queriesansQueries(s, ed, n, q); </script>
0
5
-1
8
20
 
Time Complexity: O(Q + N*E) Space Complexity: O(N*N) 
ankthon
offbeat
sanjeev2552
rutvik_56
Graph
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Find if there is a path between two vertices in a directed graph
Introduction to Data Structures
Find if there is a path between two vertices in an undirected graph
What is Data Structure: Types, Classifications and Applications
Top 50 Graph Coding Problems for Interviews
Detect Cycle in a Directed Graph using BFS
K Centers Problem | Set 1 (Greedy Approximate Algorithm)
Bridges in a graph
Water Jug problem using BFS
Real-time application of Data Structures