Open In App

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

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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)
 



Last Updated : 13 May, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads