How do you find the cheapest flight from a source to a destination with at most k stops?
Use a layered dynamic program. The cost array holds the cheapest price to reach each city using the number of flights allowed so far. Start with the source at zero and everything else at infinity, then for each allowed flight count make a copy of the array and relax every flight into the copy, using the previous layer's values.
def find_cheapest_flight(n, flights, source, destination, k):
cost = [float('inf')] * n
cost[source] = 0
for _ in range(k + 1):
next_cost = list(cost)
for u, v, price in flights:
if cost[u] + price < next_cost[v]:
next_cost[v] = cost[u] + price
cost = next_cost
return -1 if cost[destination] == float('inf') else cost[destination]
flights = [(0, 1, 100), (1, 2, 100), (2, 0, 100), (1, 2, 200)]
print(find_cheapest_flight(3, flights, 0, 2, 1))The output is 200. With at most one stop, meaning at most two flights, the route from city zero through city one to city two costs two hundred, and the direct flight from one to two at that price is the only alternative that fits in the budget.
The mechanism is the copy. Each round writes into a fresh array, so a flight can only use the distances from the previous round. That is what enforces the limit on the number of flights, and using a single array in place would let a round chain several flights together and quietly exceed the budget.
The trade-off to name is the cost. The dynamic program is O of k times E time and O of n space, which is very good. The other approach is a breadth first search over the graph that tracks how many flights have been used, which is also linear in the number of states but explores many more of them. The point to get right is the convention on stops: k stops means k intermediate airports, so k plus one flights, which is why the loop runs k plus one times. Saying which convention you are using avoids the most common off by one in this problem.