How does Dijkstra's algorithm find the shortest path from a source to every other node?
Keep a priority queue of candidate distances. Start with the source at distance zero. Repeatedly take the node with the smallest tentative distance, that distance is final, and then relax its outgoing edges to see whether going through that node gives a shorter route to any neighbour.
import heapq
def dijkstra(graph, start):
distance = {start: 0}
heap = [(0, start)]
while heap:
cost, node = heapq.heappop(heap)
if cost > distance[node]:
continue
for neighbour, weight in graph[node]:
new_cost = cost + weight
if new_cost < distance.get(neighbour, float('inf')):
distance[neighbour] = new_cost
heapq.heappush(heap, (new_cost, neighbour))
return distance
graph = {"A": [("B", 1), ("C", 4)], "B": [("C", 2)], "C": []}
print(dijkstra(graph, "A"))The output shows A at zero, B at one and C at three. The direct edge from A to C costs four, but going through B costs one plus two, which is cheaper.
The mechanism is that the node with the smallest tentative distance is settled first, and once it is settled no later path can improve it, because any alternative route must pass through some node with a distance at least as large and the edge weights are non negative. That is exactly the assumption the algorithm makes, and it is why Dijkstra fails when a negative edge exists.
The trade-off to name is the heap version against the simple array version. With a heap the cost is O of E log V, while the plain array version is O of V squared. The heap version wins for sparse graphs, the array version for small dense ones, and the heap version is what you should reach for in an interview unless the graph is tiny. The other detail is the stale entry check, which skips a popped item whose cost no longer matches the current best, since the heap can hold several entries for the same node.