Shortest path between two cities without running out of fuel
Last Updated :
23 Jul, 2025
Given a country with N cities connected by M bi-directional roads given in the form of 2D array roads[][], where P cities have fuel stations and (N - P) cities do not. The task is to compute the shortest path from City A to City B, such that a car with maximum fuel capacity of "capacity" can travel without running out of fuel.
Note: 1 unit of fuel is used to travel through any road.
Examples:
Input: N = 7, M = 6, roads = [[1, 2], [2, 3], [3, 4], [4, 5], [4, 6], [6, 7]], A = 1, B = 7, capacity = 4, P = 1, fuel stations = [5]
graphOutput: 7
Explanation: As the shortest path is 1-2-3-4-5-4-6-7
Input: N = 7, M = 6, roads = [[1, 2], [2, 3], [3, 4], [4, 5], [4, 6], [6, 7]], A = 1, B = 7, capacity = 4, P = 2, fuel stations = [5,6]
Output: 5
Explanation: As the shortest path is 1-2-3-4-6-7
Approach: To solve the problem, follow the below idea:
We can solve the problem using Breadth First Search. Start a BFS from source node by pushing the current node along with the remaining fuel in the queue. If at any node, the fuel goes to 0, we eliminate that path i.e. we don't add that node's neighbors in the queue again. At the end return the path which takes you to destination while maintaining the fuel capacity.
Step-by-step algorithm:
- Build Adjacency List:
Create an empty list (adj) for the adjacency list.
Iterate over bi-directional roads and add edges to the adjacency list. - Initialize Capacity Array:
Create an array (caps) to represent fuel capacity at each city.
Mark cities with fuel stations by setting caps[city] = capacity. - Initialize Fuel Array:
Create an array (fuel) to represent the current fuel level at each city.
Mark the starting city with the full fuel capacity. - Initialize Queue for BFS: Create a deque (que) and add the starting city with distance 0.
- Apply BFS:
Use a while loop to iterate until the queue is empty.
Pop a pair (distance, node) from the queue.
If the current node is the destination, return the distance.
Iterate over neighbors of the current node, updating their fuel levels under certain conditions.
If the condition is true, update the fuel level and enqueue the neighbor with an incremented distance. - Return -1 if Path Not Found: If the loop completes without reaching the destination, return -1, indicating no path.
Below is the implementation of the algorithm:
C++
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class Solution {
public:
int findMinRoute(int n, vector<vector<int>>& roads, vector<int>& fuelStations, int source, int destination, int capacity) {
// Defining the adjacency list
vector<vector<int>> adj(n + 1, vector<int>());
// Building the adjacency list from given roads
for (auto& road : roads) {
int u = road[0];
int v = road[1];
adj[u].push_back(v);
adj[v].push_back(u);
}
// Initializing fuel capacities for each node
vector<int> caps(n + 1, 0);
for (int node : fuelStations) {
caps[node] = capacity;
}
// Initializing fuel levels for each node
vector<int> fuel(n + 1, 0);
// Initializing the queue for BFS traversal
queue<pair<int, int>> queue;
queue.push({0, source});
fuel[source] = capacity;
// BFS traversal
while (!queue.empty()) {
auto current = queue.front();
queue.pop();
int dis = current.first;
int node = current.second;
if (node == destination) {
return dis;
}
// Exploring neighbors of the current node
for (int adjNode : adj[node]) {
// Calculating the new fuel level for the adjacent node
int newFuel = max(caps[adjNode], fuel[node] - 1);
// If the new fuel level is greater than the existing at the next node
if (newFuel > fuel[adjNode]) {
// Update the fuel level and add the adjacent node to the queue
fuel[adjNode] = newFuel;
queue.push({dis + 1, adjNode});
}
}
}
// If destination is not reachable
return -1;
}
};
// Example usage
int main() {
int n = 7;
vector<vector<int>> roads = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {4, 6}, {6, 7}};
int source = 1;
int destination = 7;
int capacity = 4;
vector<int> fuelStations = {5};
cout << Solution().findMinRoute(n, roads, fuelStations, source, destination, capacity) << endl;
return 0;
}
Java
import java.util.*;
class Solution {
public int findMinRoute(int n, int[][] roads, List<Integer> fuelStations, int source, int destination, int capacity) {
// Defining the adjacency list
List<List<Integer>> adj = new ArrayList<>();
for (int i = 0; i <= n; i++) {
adj.add(new ArrayList<>());
}
// Building the adjacency list from given roads
for (int[] road : roads) {
int u = road[0];
int v = road[1];
adj.get(u).add(v);
adj.get(v).add(u);
}
// Initializing fuel capacities for each node
int[] caps = new int[n + 1];
for (int node : fuelStations) {
caps[node] = capacity;
}
// Initializing fuel levels for each node
int[] fuel = new int[n + 1];
// Initializing the queue for BFS traversal
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{0, source});
fuel[source] = capacity;
// BFS traversal
while (!queue.isEmpty()) {
int[] current = queue.poll();
int dis = current[0];
int node = current[1];
if (node == destination) {
return dis;
}
// Exploring neighbors of the current node
for (int adjNode : adj.get(node)) {
// Calculating the new fuel level for the adjacent node
int newFuel = Math.max(caps[adjNode], fuel[node] - 1);
// If the new fuel level is greater than the existing at the next node
if (newFuel > fuel[adjNode]) {
// Update the fuel level and add the adjacent node to the queue
fuel[adjNode] = newFuel;
queue.offer(new int[]{dis + 1, adjNode});
}
}
}
// If destination is not reachable
return -1;
}
// Example usage
public static void main(String[] args) {
int n = 7;
int[][] roads = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {4, 6}, {6, 7}};
int source = 1;
int destination = 7;
int capacity = 4;
List<Integer> fuelStations = Arrays.asList(5);
System.out.println(new Solution().findMinRoute(n, roads, fuelStations, source, destination, capacity));
}
}
// This code is contributed by shivamgupta0987654321
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Solution
{
public int FindMinRoute(int n, int[][] roads, List<int> fuelStations, int source, int destination, int capacity)
{
// Defining the adjacency list
List<List<int>> adj = new List<List<int>>();
for (int i = 0; i <= n; i++)
{
adj.Add(new List<int>());
}
// Building the adjacency list from given roads
foreach (var road in roads)
{
int u = road[0];
int v = road[1];
adj[u].Add(v);
adj[v].Add(u);
}
// Initializing fuel capacities for each node
int[] caps = new int[n + 1];
foreach (int node in fuelStations)
{
caps[node] = capacity;
}
// Initializing fuel levels for each node
int[] fuel = new int[n + 1];
// Initializing the queue for BFS traversal
Queue<int[]> queue = new Queue<int[]>();
queue.Enqueue(new int[] { 0, source });
fuel[source] = capacity;
// BFS traversal
while (queue.Count > 0)
{
int[] current = queue.Dequeue();
int dis = current[0];
int node = current[1];
if (node == destination)
{
return dis;
}
// Exploring neighbors of the current node
foreach (int adjNode in adj[node])
{
// Calculating the new fuel level for the adjacent node
int newFuel = Math.Max(caps[adjNode], fuel[node] - 1);
// If the new fuel level is greater than the existing at the next node
if (newFuel > fuel[adjNode])
{
// Update the fuel level and add the adjacent node to the queue
fuel[adjNode] = newFuel;
queue.Enqueue(new int[] { dis + 1, adjNode });
}
}
}
// If destination is not reachable
return -1;
}
// Example usage
public static void Main(string[] args)
{
int n = 7;
int[][] roads = { new int[] { 1, 2 }, new int[] { 2, 3 }, new int[] { 3, 4 }, new int[] { 4, 5 }, new int[] { 4, 6 }, new int[] { 6, 7 } };
int source = 1;
int destination = 7;
int capacity = 4;
List<int> fuelStations = new List<int> { 5 };
Console.WriteLine(new Solution().FindMinRoute(n, roads, fuelStations, source, destination, capacity));
}
}
JavaScript
class Solution {
findMinRoute(n, roads, fuelStations, source, destination, capacity) {
// Defining the adjacency list
const adj = new Array(n + 1).fill(null).map(() => []);
// Building the adjacency list from given roads
for (const [u, v] of roads) {
adj[u].push(v);
adj[v].push(u);
}
// Initializing fuel capacities for each node
const caps = new Array(n + 1).fill(0);
for (const node of fuelStations) {
caps[node] = capacity;
}
// Initializing fuel levels for each node
const fuel = new Array(n + 1).fill(0);
// Initializing the queue for BFS traversal
const queue = [];
queue.push([0, source]);
fuel[source] = capacity;
// BFS traversal
while (queue.length > 0) {
const [dis, node] = queue.shift();
if (node === destination) {
return dis;
}
// Exploring neighbors of the current node
for (const adjNode of adj[node]) {
// Calculating the new fuel level for the adjacent node
const newFuel = Math.max(caps[adjNode], fuel[node] - 1);
// If the new fuel level is greater than the existing at the next node
if (newFuel > fuel[adjNode]) {
// Update the fuel level and add the adjacent node to the queue
fuel[adjNode] = newFuel;
queue.push([dis + 1, adjNode]);
}
}
}
// If destination is not reachable
return -1;
}
}
// Example usage
const n = 7;
const roads = [[1, 2], [2, 3], [3, 4], [4, 5], [4, 6], [6, 7]];
const source = 1;
const destination = 7;
const capacity = 4;
const fuelStations = [5];
console.log(new Solution().findMinRoute(n, roads, fuelStations, source, destination, capacity));
Python3
from collections import deque
class Solution:
def findMinRoute(self, n, roads, fuel_stations, source, destination, capacity):
# Defining the adjacency list
adj = [[] for _ in range(n + 1)]
# Building the adjacency list from given roads
for u, v in roads:
adj[u].append(v)
adj[v].append(u)
# Initializing fuel capacities for each node
caps = [0] * (n + 1)
for node in fuel_stations:
caps[node] = capacity
# Initializing fuel levels for each node
fuel = [0] * (n + 1)
# Initializing the queue for BFS traversal
que = deque([(0, source)])
fuel[source] = capacity
# BFS traversal
while que:
dis, node = que.popleft()
if node == destination:
return dis
# Exploring neighbors of the current node
for adjNode in adj[node]:
# Calculating the new fuel level for the adjacent node
new = max(caps[adjNode], fuel[node] - 1)
# If the new fuel level is greater than the existing at the next node
if new > fuel[adjNode]:
# Update the fuel level and add the adjacent node to the queue
fuel[adjNode] = new
que.append((dis + 1, adjNode))
# If destination is not reachable
return -1
# Example usage
n = 7
roads = [[1, 2], [2, 3], [3, 4], [4, 5], [4, 6], [6, 7]]
A = 1
B = 7
capacity = 4
fuel_stations = [5]
print(Solution().findMinRoute(n, roads, fuel_stations, A, B, capacity))
Time Complexity: O(N + M) where N is the number of cities and M is the number of roads.
Auxiliary Space: O(N)
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem