Skip to content
Related Articles

Related Articles

Improve Article
Shortest path in a graph from a source S to destination D with exactly K edges for multiple Queries
  • Last Updated : 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++




// 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 edges
void 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 code
int 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




// Java implementation of the approach
import 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 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
        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 code
public 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




# Python3 implementation of the approach
import sys,numpy as np
 
inf = sys.maxsize;
 
# Function to find the shortest path
# between S and D with exactly K edges
def 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 code
if __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#




// C# implementation of the approach
using 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

Javascript




<script>
 
// Javascript implementation of the approach
var inf = 100000000;
 
// Function to find the shortest path
// between S and D with exactly K edges
function 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 code
var n = 3;
var ed;
// Edges
ed = [ [ [ 1, 2 ], 5 ],
       [ [ 2, 3 ], 3 ],
       [ [ 3, 1 ], 4 ] ];
// Source
var s = 1;
// Queries
var q = [ [ 1, 0 ],
                              [ 2, 1 ],
                              [ 3, 1 ],
                              [ 3, 2 ],
                              [ 3, 5 ] ];
// Function to answer queries
ansQueries(s, ed, n, q);
 
</script>
Output: 
0
5
-1
8
20

 

Time Complexity: O(Q + N*E) 
Space Complexity: O(N*N)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live 




My Personal Notes arrow_drop_up
Recommended Articles
Page :