पाठ 18 / 25
Dijkstra's Algorithm and Topological Sort
Find weighted shortest paths and order dependencies.
Weights and dependencies
When edges have non-negative weights, Dijkstra's algorithm finds the shortest distance from a source to every vertex. It keeps a priority queue (a heapq min-heap) of tentative distances, repeatedly takes the closest unsettled vertex, and relaxes its edges (if going through it gives a shorter route to a neighbour, update that neighbour). With a binary heap, it runs in O((V + E) log V). Python implementations commonly push duplicate entries and skip stale ones when popped (lazy deletion). For graphs with negative weights, use Bellman–Ford; for all-pairs shortest paths on small graphs, Floyd–Warshall; and for grids or maps with a good distance estimate, A* adds a heuristic to explore fewer nodes. Topological sorting orders the vertices of a DAG so that every edge goes from earlier to later, which is exactly a valid order for build steps, course prerequisites, task scheduling and spreadsheet recalculation. Kahn's algorithm repeatedly takes vertices with no remaining incoming edges; if some vertices are never freed, the graph has a cycle. The standard library offers graphlib.TopologicalSorter (Python 3.9+).
Dijkstra with heapq and a topological sort
Shortest delivery routes and a valid course order.
import heapq
from graphlib import TopologicalSorter
def dijkstra(graph: dict[str, dict[str, int]], source: str) -> dict[str, int]:
dist = {source: 0}
heap = [(0, source)]
while heap:
d, node = heapq.heappop(heap)
if d > dist[node]:
continue # stale entry: a shorter path was found already
for neighbour, weight in graph.get(node, {}).items():
candidate = d + weight
if candidate < dist.get(neighbour, float("inf")):
dist[neighbour] = candidate # relax the edge
heapq.heappush(heap, (candidate, neighbour))
return dist
roads = {
"Warehouse": {"A": 4, "B": 1},
"B": {"A": 2, "C": 5},
"A": {"C": 1},
"C": {},
}
print(dijkstra(roads, "Warehouse")) # {'Warehouse': 0, 'A': 3, 'B': 1, 'C': 4}
prereqs = { # course: set of prerequisites
"algorithms": {"data-structures"},
"data-structures": {"python-basics"},
"web-apis": {"python-basics"},
"capstone": {"algorithms", "web-apis"},
}
order = list(TopologicalSorter(prereqs).static_order())
print(order) # python-basics first, capstone last; e.g. ['python-basics', 'data-structures', 'web-apis', 'algorithms', 'capstone']
# a cycle raises graphlib.CycleError:
# TopologicalSorter({"a": {"b"}, "b": {"a"}}).static_order()Dijkstra needs non-negative weights
With a negative edge, a settled vertex could later be reached more cheaply, breaking Dijkstra's assumptions. Use Bellman–Ford for negative weights, and check for negative cycles.
त्वरित जाँच: What does a topological sort require of the graph?
- It must be a directed acyclic graph (DAG)
- It must be undirected
- It must be weighted
- It must be complete
Answer
It must be a directed acyclic graph (DAG) — A cycle means no order can put every vertex after all its prerequisites.