There is a country of n cities numbered from 0 to n - 1 where all the cities are connected by bi-directional roads. The roads are represented as a 2D integer array edges where edges[i] = [xi, yi, timei] denotes a road between cities xi and yi that takes timei minutes to travel. There may be multiple roads of differing travel times connecting the same two cities, but no road connects a city to itself.
Each time you pass through a city, you must pay a passing fee. This is represented as a 0-indexed integer array passingFees of length n where passingFees[j] is the amount of dollars you must pay when you pass through city j.
In the beginning, you are at city 0 and want to reach city n - 1 in maxTime minutes or less. The cost of your journey is the summation of passing fees for each city that you passed through at some moment of your journey (including the source and destination cities).
Given maxTime, edges, and passingFees, return the minimum cost to complete your journey, or -1 if you cannot complete it within maxTime minutes.
Example 1:

Input: maxTime = 30, edges = [[0,1,10],[1,2,10],[2,5,10],[0,3,1],[3,4,10],[4,5,15]], passingFees = [5,1,2,20,20,3] Output: 11 Explanation: The path to take is 0 -> 1 -> 2 -> 5, which takes 30 minutes and has $11 worth of passing fees.
Example 2:

Input: maxTime = 29, edges = [[0,1,10],[1,2,10],[2,5,10],[0,3,1],[3,4,10],[4,5,15]], passingFees = [5,1,2,20,20,3] Output: 48 Explanation: The path to take is 0 -> 3 -> 4 -> 5, which takes 26 minutes and has $48 worth of passing fees. You cannot take path 0 -> 1 -> 2 -> 5 since it would take too long.
Example 3:
Input: maxTime = 25, edges = [[0,1,10],[1,2,10],[2,5,10],[0,3,1],[3,4,10],[4,5,15]], passingFees = [5,1,2,20,20,3] Output: -1 Explanation: There is no way to reach city 5 from city 0 within 25 minutes.
Constraints:
1 <= maxTime <= 1000n == passingFees.length2 <= n <= 1000n - 1 <= edges.length <= 10000 <= xi, yi <= n - 11 <= timei <= 10001 <= passingFees[j] <= 1000 When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The core idea is to explore absolutely every possible path from the starting point to the destination. We calculate the cost of each path and eliminate those that don't meet the time limit. Finally, we choose the path with the lowest cost from all possible valid paths.
Here's how the algorithm would work step-by-step:
def minimum_cost_to_reach_destination_brute_force(max_time, passing_fees, time_costs):
number_of_cities = len(passing_fees)
minimum_possible_cost = float('inf')
def explore_all_paths(current_city, current_time, current_cost):
nonlocal minimum_possible_cost
# If time exceeds max_time, stop
if current_time > max_time:
return
# If reached the destination
if current_city == number_of_cities - 1:
minimum_possible_cost = min(minimum_possible_cost, current_cost + passing_fees[current_city])
return
# Explore all possible next cities
for next_city in range(number_of_cities):
if next_city != current_city:
# Ensuring we don't revisit the same city
time_to_next_city = time_costs[current_city][next_city]
# Recursive call to explore paths
explore_all_paths(next_city, current_time + time_to_next_city, current_cost + passing_fees[current_city])
# Start exploring from city 0 with initial time 0 and cost 0
explore_all_paths(0, 0, 0)
# If no path is found within max_time, return -1
if minimum_possible_cost == float('inf'):
return -1
else:
return minimum_possible_costThe best way to solve this problem is to explore possible paths in a smart order, keeping track of the fastest ways to get somewhere. We can make use of an advanced searching strategy to effectively find the lowest cost to reach the destination within the given time limit.
Here's how the algorithm would work step-by-step:
import heapq
def minCost(max_time, city_costs, allowed_travel_times):
number_of_cities = len(city_costs)
minimum_costs = [float('inf')] * number_of_cities
minimum_costs[0] = city_costs[0]
# Use a priority queue to explore promising paths first.
priority_queue = [(city_costs[0], 0, 0)]
while priority_queue:
current_cost, current_city, current_time = heapq.heappop(priority_queue)
# If we've exceeded the allowed time, this path is invalid.
if current_time > max_time:
continue
# If we've reached the destination, return the cost
if current_city == number_of_cities - 1:
return current_cost
for next_city, travel_time in enumerate(allowed_travel_times[current_city]):
if travel_time > 0:
new_time = current_time + travel_time
# Prune paths that exceed the time limit
if new_time <= max_time:
new_cost = current_cost + city_costs[next_city]
# Update minimum cost if a better path is found
if new_cost < minimum_costs[next_city]:
minimum_costs[next_city] = new_cost
# Add the new state to the priority queue
heapq.heappush(priority_queue, (new_cost, next_city, new_time))
return -1| Case | How to Handle |
|---|---|
| Empty `passingFees` or `timeLimits` array, or null input | Return -1 immediately as there's no path or time to calculate the cost. |
| `n` (number of cities) is 1, but `maxTime` is positive | Return 0 since we're already at the destination with no travel required. |
| `maxTime` is 0, but `n` is greater than 1 | Return -1 because it's impossible to reach the destination in zero time. |
| A city is unreachable within `maxTime`. | The algorithm should propagate the maximum cost (infinity) and eventually return -1 if the destination remains unreachable. |
| `passingFees` or `timeLimits` contain negative numbers. | Return -1, since negative fees or travel times are invalid inputs. |
| `timeLimits` values are very large, potentially leading to integer overflow when summed. | Use `long` data type for time calculations to prevent overflow. |
| The graph contains cycles and the optimal path uses a cycle | Dijkstra's algorithm with time limit handles cycles by tracking the minimum cost to reach each node within the allowed time, effectively ignoring redundant cycles. |
| Large input sizes for `n` and number of edges may lead to Time Limit Exceeded (TLE). | Optimize algorithm using priority queue (heap) with Dijkstra or A* search to efficiently explore possible paths. |