I am trying to solve LeetCode problem #787, "Cheapest Flights Within K Stops."
"There are n cities connected by some number of flights. You are given an array flights where flights[i] = [fromi, toi, pricei] indicates that there is a flight from city fromi to city toi with cost pricei. You are also given three integers src, dst, and k, return the cheapest price from src to dst with at most k stops. If there is no such route, return -1."
However, I am encountering an issue with a specific testcase:
flights = [[0,1,5],[1,2,5],[0,3,2],[3,1,2],[1,4,1],[4,2,1]],
n = 5,
src = 0,
dst = 2,
k = 2
The expected answer is 7, but my code is returning 9. I have spent the last 2 hours debugging the code, but I cant seem to find the issue. I would appreciate if someone can point out whats wrong with the code.
code:
class minHeap {
constructor() {
this.nodes = []
}
enqueue(node, priority, stopsCount) {
if(this.isEmpty()) {
this.nodes.push([node, priority, stopsCount])
} else {
let added = false;
for(let i = 0; i < this.nodes.length; i++) {
if(this.nodes[i][1] > priority) {
this.nodes.splice(i, 0, [node, priority, stopsCount])
added = true
break;
}
}
if(!added) {
this.nodes.push([node, priority, stopsCount])
}
}
}
dequeue() {
return this.nodes.shift()
}
isEmpty() {
return this.nodes.length === 0
}
}
var findCheapestPrice = function(n, flights, src, dst, k) {
const graph = {}
const prices = {}
for(let i = 0; i < n; i++) {
graph[i] = []
if (i == src) {
prices[i] = 0
} else {
prices[i] = Infinity
}
}
for(let [ from, to, price ] of flights) {
graph[from].push([ to, price ])
}
const heap = new minHeap()
heap.enqueue(src, 0, 0)
while (!heap.isEmpty()) {
const [ airport, price, stopsCount ] = heap.dequeue()
for (let neighbor of graph[airport]) {
const [ neighborAirport, neighborPrice ] = neighbor
const priceToNeighbor = neighborPrice + price
if (prices[neighborAirport] > priceToNeighbor && stopsCount <= k) {
prices[neighborAirport] = priceToNeighbor
heap.enqueue(neighborAirport, priceToNeighbor, stopsCount+1)
}
}
}
return prices[dst] == Infinity ? -1 : prices[dst]
};
2
Answers
I don’t have enough time to debug exactly what’s wrong but I feel something is wrong with your enqueuing priority. Removing that optimization causes the program to work correctly:
I tried submitting the above code to LeetCode (sorry about that, I didn’t mean to plagarize, just want to test), it passes all test cases.
Update: this fix may work by luck though I cannot find a counter example yet. In fact, I think without the priority, it should work for all cases (see comments below and the other answer). Even with this complicated graph this code works:
The scheme to update and only enqueue stops prioritised by cost doesn’t work in this particular example because the cost to get to airport 4 is set as 5 after 3 stops (including the last):
[0,3,2] -> [3,1,2] -> [1,4,1]
. But in order to reach airport 2 optimally, we need the interim state where we reach airport 4 with cost 6 but the priority scheme prevents this:I don’t believe Dijkstra can be used generally to optimise edge cost to a destination where the number of edges is restricted. Other dynamic programming or graph algorithms can assist with that.