Shortest Path with At most k Nodes

Last Updated : 18 Jul, 2026

Given a weighted directed graph represented by a 2D array edges[][], where each element edges[i] = {u, v, w} represents a directed edge from vertex u to vertex v with cost w, find the minimum cost required to travel from a given source vertex src to a destination vertex dst. You are also given an integer k representing the maximum number of nodes allowed in the path. Return the minimum possible cost of such a path containing at most k nodes. If no such path exists, return -1.

Examples:

Input: n=6, edges[][] = [[0, 1, 10], [1, 2, 20], [1, 3, 10], [2, 5, 30], [3, 4, 10], [4, 5, 10]], src=0, dst=5, k=2
Output: 60
Explanation:

a

There can be a route marked with a red arrow that takes cost =  10+10+10+10 = 40 using three nodes. And route marked with green arrow takes cost = 10+20+30=60 using two nodes. But since there can be at most 2 nodes, the answer will be 60.

Input: n=3, edges[][] = [[0, 1, 10], [0, 2, 50], [1, 2, 10]], src=0, dst=2, k=1
Output:  20
Explanation:

aa

Since the k is 1, then the green-colored path can be taken with a minimum cost of 20.

Try It Yourself
redirect icon

Using BFS Traversal - O(k*E) Time and O(V + E) Space

Use Breadth-First Search (BFS) to explore all possible paths level by level while keeping track of the minimum cost to reach each node. Since each BFS level represents one more node in the path, we continue the traversal only up to k nodes. Whenever a cheaper cost to reach a node is found, we update it and push that node into the queue for further exploration.

Steps:

  • Increase the value of k by 1 to account for the destination node.
  • Create an adjacency list from the given graph.
  • Initialize a prices[] array with -1 to store the minimum cost to reach each node.
  • Initialize a queue and push {src, 0} into it, where 0 is the current cost.
  • Run BFS until the queue becomes empty or k becomes 0.
  • For every node popped from the queue, traverse all its adjacent nodes.
  • If the adjacent node is not visited before or a cheaper cost is found, update its cost in prices[].
  • Push the updated node and its cost into the queue for further traversal.
  • Decrease k after processing one complete BFS level.
  • Return prices[dst] as the final answer. If it remains -1, then no valid path exists.
C++
#include <iostream>
using namespace std;

// Function to find the minimum cost
// from src to dst with at most k stops
int findCheapestCost(int n, vector<vector<int> >& edges, int src, int dst, int k) {
    
      //if the destination cannot be reached
      if(dst > n)
      return -1;
      
    // Increase k by 1 Because on reaching
    // destination, k becomes k+1
    k = k + 1;

    // Making Adjacency List
    vector<pair<int, int> > adj[n];

    // U->{v, wt}
    for (auto it : edges) {
        adj[it[0]].push_back({ it[1], it[2] });
    }

    // Vector for Storing prices
    vector<int> prices(n, -1);

    // Queue for storing vertex and cost
    queue<pair<int, int> > q;

    q.push({ src, 0 });
    prices[src] = 0;

    while (!q.empty()) {

        // If all the k stops are used,
        // then break
        if (k == 0)
            break;

        int sz = q.size();
        while (sz--) {
            int node = q.front().first;
            int cost = q.front().second;
            q.pop();

            for (auto it : adj[node]) {
                if (prices[it.first] == -1
                    or cost + it.second
                           < prices[it.first]) {
                    prices[it.first] = cost + it.second;
                    q.push({ it.first, cost + it.second });
                }
            }
        }
        k--;
    }
    return prices[dst];
}

int main() {
    int n = 6;
    vector<vector<int> > edges
        = { { 0, 1, 10 }, { 1, 2, 20 }, { 2, 5, 30 }, { 1, 3, 10 }, { 3, 4, 10 }, { 4, 5, 10 } };

    int src = 0;
    int dst = 5;
    int k = 2;
    cout << findCheapestCost(n, edges, src, dst, k) << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {

    // Function to find the minimum cost
    // from src to dst with at most k stops
    static int findCheapestCost(int n, int[][] edges,
                                int src, int dst, int k) {

        // if the destination cannot be reached
        if (dst >= n)
            return -1;

        // Increase k by 1 Because on reaching
        // destination, k becomes k+1
        k = k + 1;

        // Making Adjacency List
        ArrayList<ArrayList<int[]>> adj = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            adj.add(new ArrayList<>());
        }

        // U->{v, wt}
        for (int[] it : edges) {
            adj.get(it[0]).add(new int[] {it[1], it[2]});
        }

        // Array for storing prices
        int[] prices = new int[n];

        Arrays.fill(prices, -1);

        // Queue for storing vertex and cost
        Queue<int[]> q = new LinkedList<>();

        q.offer(new int[] {src, 0});

        prices[src] = 0;

        while (!q.isEmpty()) {

            // If all the k stops are used,
            // then break
            if (k == 0)
                break;

            int sz = q.size();

            while (sz-- > 0) {

                int[] curr = q.poll();

                int node = curr[0];
                int cost = curr[1];

                for (int[] it : adj.get(node)) {

                    if (prices[it[0]] == -1
                        || cost + it[1] < prices[it[0]]) {

                        prices[it[0]] = cost + it[1];

                        q.offer(new int[] {
                            it[0],
                            cost + it[1]
                        });
                    }
                }
            }

            k--;
        }

        return prices[dst];
    }

    public static void main(String[] args) {

        int n = 6;

        int[][] edges = {
            {0, 1, 10},
            {1, 2, 20},
            {2, 5, 30},
            {1, 3, 10},
            {3, 4, 10},
            {4, 5, 10}
        };

        int src = 0;
        int dst = 5;
        int k = 2;

        System.out.println(
            findCheapestCost(n, edges, src, dst, k)
        );
    }
}
Python
from collections import deque

# Function to find the minimum cost
# from src to dst with at most k stops
def findCheapestCost(n, edges, src, dst, k):

    # if the destination cannot be reached
    if dst > n:
      return -1;
      
    # Increase k by 1 Because on reaching
    # destination, k becomes k+1
    k = k + 1

    # Making Adjacency List
    adj = [[] for _ in range(n)]

    # U->{v, wt}
    for it in edges:
        adj[it[0]].append([it[1], it[2]])

    # Vector for Storing prices
    prices = [-1 for _ in range(n)]

    # Queue for storing vertex and cost
    q = deque()

    q.append([src, 0])
    prices[src] = 0

    while (len(q) != 0):

        # If all the k stops are used,
        # then break
        if (k == 0):
            break

        sz = len(q)
        while (True):
            sz -= 1

            pr = q.popleft()

            node = pr[0]
            cost = pr[1]

            for it in adj[node]:
                if (prices[it[0]] == -1
                        or cost + it[1]
                        < prices[it[0]]):
                    prices[it[0]] = cost + it[1]
                    q.append([it[0], cost + it[1]])

            if sz == 0:
                break
        k -= 1

    return prices[dst]

if __name__ == "__main__":

    n = 6
    edges = [
            [0, 1, 10],
            [1, 2, 20],
            [2, 5, 30],
            [1, 3, 10],
            [3, 4, 10],
            [4, 5, 10]]

    src = 0
    dst = 5
    k = 2
    print(findCheapestCost(n, edges, src, dst, k))

    # This code is contributed by rakeshsahni
C#
using System;
using System.Collections.Generic;

class Program
{
    // Function to find the minimum cost
    // from src to dst with at most k stops
    public static int findCheapestCost(int n, int[][] edges,
                                       int src, int dst, int k)
    {
        // if the destination cannot be reached
        if (dst > n)
        {
            return -1;
        }

        // Increase k by 1 Because on reaching
        // destination, k becomes k+1
        k = k + 1;

        // Making Adjacency List
        List<List<int[]>> adj = new List<List<int[]>>();

        for (int i = 0; i < n; i++)
        {
            adj.Add(new List<int[]>());
        }

        // U->{v, wt}
        foreach (int[] it in edges)
        {
            adj[it[0]].Add(new int[] { it[1], it[2] });
        }

        // Vector for Storing prices
        int[] prices = new int[n];

        for (int i = 0; i < n; i++)
        {
            prices[i] = -1;
        }

        // Queue for storing vertex and cost
        Queue<int[]> q = new Queue<int[]>();

        q.Enqueue(new int[] { src, 0 });

        prices[src] = 0;

        while (q.Count != 0)
        {
            // If all the k stops are used,
            // then break
            if (k == 0)
            {
                break;
            }

            int sz = q.Count;

            while (sz-- > 0)
            {
                int[] pr = q.Dequeue();

                int node = pr[0];
                int cost = pr[1];

                foreach (int[] it in adj[node])
                {
                    if (prices[it[0]] == -1
                        || cost + it[1] < prices[it[0]])
                    {
                        prices[it[0]] = cost + it[1];

                        q.Enqueue(new int[] { it[0], cost + it[1] });
                    }
                }
            }

            k--;
        }

        return prices[dst];
    }

    public static void Main()
    {
        int n = 6;

        int[][] edges = {
            new int[] {0, 1, 10},
            new int[] {1, 2, 20},
            new int[] {2, 5, 30},
            new int[] {1, 3, 10},
            new int[] {3, 4, 10},
            new int[] {4, 5, 10}
        };

        int src = 0;
        int dst = 5;
        int k = 2;

        Console.WriteLine(findCheapestCost(n, edges, src, dst, k));
    }
}
JavaScript
function findCheapestCost(n, edges, src, dst, k) {
    
  // if the destination cannot be reached
  if (dst > n) {
    return -1;
  }

  // Increase k by 1 Because on reaching
  // destination, k becomes k+1
  k = k + 1;

  // Making Adjacency List
  let adj = Array.from({ length: n }, () => []);
  for (let i = 0; i < edges.length; i++) {
    adj[edges[i][0]].push([edges[i][1], edges[i][2]]);
  }

  // Vector for Storing prices
  let prices = Array.from({ length: n }, () => -1);

  // Queue for storing vertex and cost
  let q = [];
  q.push([src, 0]);
  prices[src] = 0;

  while (q.length != 0) {
      
    // If all the k stops are used,
    // then break
    if (k == 0) {
      break;
    }

    let sz = q.length;
    while (sz > 0) {
      sz -= 1;
      let pr = q.shift();
      let node = pr[0];
      let cost = pr[1];

      for (let i = 0; i < adj[node].length; i++) {
        let it = adj[node][i];
        if (prices[it[0]] == -1 || cost + it[1] < prices[it[0]]) {
          prices[it[0]] = cost + it[1];
          q.push([it[0], cost + it[1]]);
        }
      }

      if (sz == 0) {
        break;
      }
    }

    k -= 1;
  }

  return prices[dst];
}

// Driver Code
let n = 6;
let edges = [  [0, 1, 10],
  [1, 2, 20],
  [2, 5, 30],
  [1, 3, 10],
  [3, 4, 10],
  [4, 5, 10],
];
let src = 0;
let dst = 5;
let k = 2;

console.log(findCheapestCost(n, edges, src, dst, k));

Output
60

Using Bellman-Ford Relaxation - O(k*E) Time and O(V) Space

The idea is to relax all the edges at most k + 1 times because a path with at most k nodes can contain at most k + 1 edges. For every iteration, we try to minimize the cost to reach each node using the previously computed costs, ensuring that only paths within the allowed number of nodes are considered.

Steps:

  • Initialize a cost[] array with a very large value and set the source node cost as 0.
  • Run the loop k + 1 times because at most k nodes means at most k + 1 edges.
  • In every iteration, create a temporary array curr to store updated minimum costs.
  • Traverse all edges and relax an edge if a cheaper path to the destination node is found.
  • After all iterations, return the minimum cost to reach dst; if unreachable, return -1.
C++
#include <iostream>
#include <vector>
using namespace std;

// Function to find the minimum cost
// from src to dst with at most k stops
int findCheapestCost(int n, vector<vector<int>>& edges,
                   int src, int dst, int k) {

    const int maxCost = 1000000;

    // Vector for storing minimum cost
    vector<int> cost(n, maxCost);

    cost[src] = 0;

    // Relax all edges at most k + 1 times
    for (int i = 0; i <= k; i++) {

        vector<int> curr = cost;

        for (auto& edge : edges) {

            int u = edge[0];
            int v = edge[1];
            int wt = edge[2];

            // If source node is reachable
            if (cost[u] != maxCost) {

                // Relax the edge
                curr[v] = min(curr[v], cost[u] + wt);
            }
        }

        cost = curr;
    }

    // If destination is unreachable
    if (cost[dst] == maxCost)
        return -1;

    return cost[dst];
}

int main() {

    int n = 6;

    vector<vector<int>> edges = {
        {0, 1, 10},
        {1, 2, 20},
        {2, 5, 30},
        {1, 3, 10},
        {3, 4, 10},
        {4, 5, 10}
    };

    int src = 0;
    int dst = 5;
    int k = 2;

    cout << findCheapestCost(n, edges, src, dst, k)
         << endl;

    return 0;
}
Java
import java.util.*;

class Solution {

    // Function to find the minimum cost
    // from src to dst with at most k stops
    public static int findCheapestCost(int n, int[][] edges,
                                       int src, int dst, int k) {

        int maxCost = 1000000;

        // Array for storing minimum cost
        int[] cost = new int[n];

        Arrays.fill(cost, maxCost);

        cost[src] = 0;

        // Relax all edges at most k + 1 times
        for (int i = 0; i <= k; i++) {

            int[] curr = cost.clone();

            for (int[] edge : edges) {

                int u = edge[0];
                int v = edge[1];
                int wt = edge[2];

                // If source node is reachable
                if (cost[u] != maxCost) {

                    // Relax the edge
                    curr[v] = Math.min(curr[v], cost[u] + wt);
                }
            }

            cost = curr;
        }

        // If destination is unreachable
        if (cost[dst] == maxCost)
            return -1;

        return cost[dst];
    }

    public static void main(String[] args) {

        int n = 6;

        int[][] edges = {
            {0, 1, 10},
            {1, 2, 20},
            {2, 5, 30},
            {1, 3, 10},
            {3, 4, 10},
            {4, 5, 10}
        };

        int src = 0;
        int dst = 5;
        int k = 2;

        System.out.println(findCheapestCost(n, edges, src, dst, k));
    }
}
Python
# Function to find the minimum cost
# from src to dst with at most k stops
def findCheapestCost(n, edges, src, dst, k):

    maxCost = 1000000

    # List for storing minimum cost
    cost = [maxCost] * n

    cost[src] = 0

    # Relax all edges at most k + 1 times
    for i in range(k + 1):

        curr = cost[:]

        for edge in edges:

            u = edge[0]
            v = edge[1]
            wt = edge[2]

            # If source node is reachable
            if cost[u] != maxCost:

                # Relax the edge
                curr[v] = min(curr[v], cost[u] + wt)

        cost = curr

    # If destination is unreachable
    if cost[dst] == maxCost:
        return -1

    return cost[dst]


n = 6

edges = [
    [0, 1, 10],
    [1, 2, 20],
    [2, 5, 30],
    [1, 3, 10],
    [3, 4, 10],
    [4, 5, 10]
]

src = 0
dst = 5
k = 2

print(findCheapestCost(n, edges, src, dst, k))
C#
using System;

class Program
{
    // Function to find the minimum cost
    // from src to dst with at most k stops
    public static int findCheapestCost(int n, int[][] edges,
                                       int src, int dst, int k)
    {
        int maxCost = 1000000;

        // Array for storing minimum cost
        int[] cost = new int[n];

        for (int i = 0; i < n; i++)
        {
            cost[i] = maxCost;
        }

        cost[src] = 0;

        // Relax all edges at most k + 1 times
        for (int i = 0; i <= k; i++)
        {
            int[] curr = (int[])cost.Clone();

            foreach (int[] edge in edges)
            {
                int u = edge[0];
                int v = edge[1];
                int wt = edge[2];

                // If source node is reachable
                if (cost[u] != maxCost)
                {
                    // Relax the edge
                    curr[v] = Math.Min(curr[v], cost[u] + wt);
                }
            }

            cost = curr;
        }

        // If destination is unreachable
        if (cost[dst] == maxCost)
            return -1;

        return cost[dst];
    }

    static void Main()
    {
        int n = 6;

        int[][] edges = {
            new int[] {0, 1, 10},
            new int[] {1, 2, 20},
            new int[] {2, 5, 30},
            new int[] {1, 3, 10},
            new int[] {3, 4, 10},
            new int[] {4, 5, 10}
        };

        int src = 0;
        int dst = 5;
        int k = 2;

        Console.WriteLine(findCheapestCost(n, edges, src, dst, k));
    }
}
JavaScript
// Function to find the minimum cost
// from src to dst with at most k stops
function findCheapestCost(n, edges, src, dst, k) {

    const maxCost = 1000000;

    // Array for storing minimum cost
    let cost = new Array(n).fill(maxCost);

    cost[src] = 0;

    // Relax all edges at most k + 1 times
    for (let i = 0; i <= k; i++) {

        let curr = [...cost];

        for (let edge of edges) {

            let u = edge[0];
            let v = edge[1];
            let wt = edge[2];

            // If source node is reachable
            if (cost[u] != maxCost) {

                // Relax the edge
                curr[v] = Math.min(curr[v], cost[u] + wt);
            }
        }

        cost = curr;
    }

    // If destination is unreachable
    if (cost[dst] == maxCost)
        return -1;

    return cost[dst];
}

let n = 6;

let edges = [
    [0, 1, 10],
    [1, 2, 20],
    [2, 5, 30],
    [1, 3, 10],
    [3, 4, 10],
    [4, 5, 10]
];

let src = 0;
let dst = 5;
let k = 2;

console.log(findCheapestCost(n, edges, src, dst, k));

Output
60
Comment