Step 1 Understand it
Remember it by
Weighted edges? Dijkstra: always expand the cheapest known node next (a heap).
Watch it happen
Read the animation as text
- A signal starts at node 2. How long until every node hears it? Dijkstra: always settle the closest node not yet settled. A heap keeps the closest on top.
- Pop (0, 2): the closest unsettled node. Its time is final: 0. Push its neighbours: 1 at 0 + 1 = 1, 3 at 0 + 1 = 1.
- Pop (1, 1): the closest unsettled node. Its time is final: 1. Push its neighbours: 4 at 1 + 3 = 4.
- Pop (1, 3): the closest unsettled node. Its time is final: 1. Push its neighbours: 4 at 1 + 1 = 2.
- Pop (2, 4): settle node 4 at time 2. No unsettled neighbours to push.
- Pop (4, 4): node 4 is already settled at a shorter time. This old entry is stale — skip it.
- Every node is settled. The last to hear the signal is at time 2: the answer. Node 4 was pushed twice (4 via node 1, 2 via node 3) — the heap handed out the cheaper one first.
The idea
When edges have different costs, BFS isn't enough. Dijkstra uses a min-heap to always settle the cheapest unsettled node. Related tools: Bellman-Ford when there's a limit on the number of edges (or negative weights), Prim's or Kruskal's for the cheapest way to connect everything (minimum spanning tree), and topological sort for ordering.
Picture it
flowchart LR
S(("2: source")) -->|"1"| A(("1"))
S -->|"1"| B(("3"))
B -->|"1"| D(("4"))
A -->|"3"| DAnalogy
Water spreading from a source through pipes of different lengths. It reaches near places first, and the first time it reaches a place is via the shortest route.
Where the analogy breaks
Water spreads everywhere at once; Dijkstra settles one node at a time. It also fails with negative edge costs, which water has no equivalent of.
More detail
What it is
Advanced Graphs tackle problems where all paths are NOT created equal. Instead of just seeing if A connects to B, what if the road from A to B costs $10, but the road from A to C costs $5? Now we're dealing with *Weighted Cost* networks, *Directed* rules, or *Disjoint Sets*.
When to use it
- When finding the Absolute Cheapest/Shortest path in a Weighted Graph (Dijkstra's Algorithm).
- When determining if a Directed Graph has a cycle (Course Schedule problems).
- When grouping highly separate islands rapidly (Union-Find).
- When finding the cheapest way to connect everything (Minimum Spanning Tree).
How it works
There are 3 major magic spells here:\n1. **Dijkstra's**: It's just BFS, but instead of a standard Queue, you use a PriorityQueue (Min-Heap) so it always explores the cheapest available path first!\n2. **Topological Sort**: Used to determine the valid order of tasks when 'Task A' must be completed before 'Task B'.\n3. **Union-Find**: An incredibly fast way to group components into separate 'sets' and check if two nodes belong to the same set.
Example walkthrough
Input: edges=[[0,1,cost:10], [0,2,cost:1], [2,1,cost:2]]. Find cheapest 0 to 1.
- Start 0 cost 0. MinHeap=[(cost 0, Node 0)].
- Pop 0. Neighbors: Node 1 cost 10, Node 2 cost 1. MinHeap=[(1, Node 2), (10, Node 1)].
- Pop (1, Node 2). Neighbors: 2 gets to 1 for cost 2. Total cost = 1 (from 0->2) + 2 (from 2->1) = 3. Add to Heap. MinHeap=[(3, Node 1), (10, Node 1)].
- Pop (3, Node 1). Reached Target 1! Total Cost is 3. (We completely ignored the expensive 10 cost path!)
Result: 3
Related patterns
- Heap / Priority Queue: Dijkstra's is essentially useless without a highly efficient PriorityQueue.
Step 2 Recognise it
Words that signal it
- 'Minimum cost / time / delay' with weighted edges
- 'Within k stops' → Bellman-Ford (k + 1 rounds)
- 'Connect all points with minimum total cost' → minimum spanning tree
- 'Order of letters / tasks from rules' → topological sort
- 'Minimise the maximum along a path' (Swim in Rising Water) → Dijkstra on the max
Don't confuse it with
- Graphs (BFS): All edges cost the same → plain BFS. Different costs → Dijkstra.
- Dynamic Programming: Bellman-Ford is DP over the number of edges used — reach for it when the number of steps is limited.
Gut check
Shortest path, but the edges have different weights? → Dijkstra with a heap.
How to recognise it in an interview
The problem talks about 'Prerequisites', 'Cheapest network', 'Connecting all points', or gives an edges array WITH a third weight value.
Step 3 The template
The general shape. Adapt it to each problem rather than learning one solution per problem.
import heapq
def dijkstra(adj, source):
# adj[u] = list of (v, cost)
dist = {}
heap = [(0, source)]
while heap:
d, u = heapq.heappop(heap)
if u in dist:
continue # already settled with a cheaper cost
dist[u] = d
for v, cost in adj[u]:
if v not in dist:
heapq.heappush(heap, (d + cost, v))
return distThe same template in Java
class Solution {
// Union-Find (Disjoint Set) Template
int[] parent;
public int find(int i) {
// Find root and compress path
if (parent[i] == i) return i;
return parent[i] = find(parent[i]);
}
public boolean union(int i, int j) {
int rootI = find(i), rootJ = find(j);
if (rootI == rootJ) return false; // Already connected! (CYCLE FOUND)
parent[rootI] = rootJ; // Connect them
return true;
}
}Common mistakes
- Not skipping a node popped a second time (a stale, more expensive entry).
- Updating prices in place during a Bellman-Ford round, which lets one round use more than one extra edge — copy the array first.
- Using Dijkstra with a 'k stops' limit: the cheapest path may use too many stops.
- Confusing Dijkstra's algorithm (Weighted Shortest Path) with standard BFS (Unweighted Shortest Path).
- Forgetting to initialize the Parent array to
parent[i] = iin a Union-Find object.
Step 4 Watch it run
Two problems, traced step by step exactly as the code runs.
Easy example: Network Delay Time (Dijkstra)
Input: times = [[2,1,1],[2,3,1],[3,4,1],[1,4,3]], n = 4, k = 2
| popped | action | settled times |
|---|---|---|
| node 2 (time 0) | settle it; push 1 at 1, 3 at 1 | {'2': 0} |
| node 1 (time 1) | settle it; push 4 at 4 | {'1': 1, '2': 0} |
| node 3 (time 1) | settle it; push 4 at 2 | {'1': 1, '2': 0, '3': 1} |
| node 4 (time 2) | settle it; no new neighbours | {'1': 1, '2': 0, '3': 1, '4': 2} |
| node 4 (time 4) | already settled → skip | {'1': 1, '2': 0, '3': 1, '4': 2} |
Result: 2
Notice: Node 4 is pushed twice (cost 4 and cost 2); the heap pops the cheaper one first, and the stale entry is skipped.
import heapq
from collections import defaultdict
def network_delay_time(times, n, k):
adj = defaultdict(list)
for u, v, w in times:
adj[u].append((v, w))
dist, heap = {}, [(0, k)]
while heap:
d, u = heapq.heappop(heap)
if u in dist:
continue
dist[u] = d
for v, w in adj[u]:
if v not in dist:
heapq.heappush(heap, (d + w, v))
return max(dist.values()) if len(dist) == n else -1Medium example: Cheapest Flights Within K Stops (Bellman-Ford)
Input: n = 4, flights = [[0,1,100],[1,2,100],[2,0,100],[1,3,600],[2,3,200]], src = 0, dst = 3, k = 1
| round | improvements | prices |
|---|---|---|
| start | only the source is free | [0, ∞, ∞, ∞] |
| round 1 (≤ 0 stops) | 0→1: 0 + 100 = 100 | [0, 100, ∞, ∞] |
| round 2 (≤ 1 stops) | 1→2: 100 + 100 = 200; 1→3: 100 + 600 = 700 | [0, 100, 200, 700] |
Result: 700
Notice: Round r allows r edges. 0 → 1 → 2 → 3 costs only 400 but needs 2 stops, so with k = 1 the answer is 700.
def find_cheapest_price(n, flights, src, dst, k):
prices = [float('inf')] * n
prices[src] = 0
for _ in range(k + 1): # k stops = k + 1 flights
tmp = prices[:] # copy: one more flight per round
for u, v, w in flights:
if prices[u] + w < tmp[v]:
tmp[v] = prices[u] + w
prices = tmp
return prices[dst] if prices[dst] != float('inf') else -1Step 5 Practise
Read each question and say the pattern and the trick out loud before you open the answer. Then solve it on LeetCode. Tick a problem once you've solved it on your own: it comes back for review tomorrow, then after 3, 7, 14 and 30 days, then every month, on the DSA page.
Medium
-
Network Delay Time Medium
A signal starts at node k; how long until every node receives it, with weighted travel times?
Show answer
Technique: Dijkstra
The clue: Shortest times with weighted edges, from one source.
The trick: Dijkstra from k; the answer is the largest shortest time (−1 if some node is never reached).
-
Connect all points with the smallest total Manhattan distance.
Show answer
Technique: Minimum spanning tree (Prim's)
The clue: 'Connect everything with minimum total cost'.
The trick: Prim's: grow a tree from one point, always adding the cheapest edge to a new point (min-heap).
-
Find the cheapest price from src to dst using at most k stops.
Show answer
Technique: Bellman-Ford with k + 1 rounds
The clue: Cheapest path with a limit on the number of edges.
The trick: Run k + 1 rounds of edge relaxation, copying the prices each round so each round adds only one flight.
Hard
-
Use every ticket exactly once to build the itinerary from JFK, choosing the alphabetically smallest when there's a choice.
Show answer
Technique: Hierholzer's algorithm (Eulerian path)
The clue: 'Use every edge exactly once'.
The trick: Sort destinations; DFS taking the smallest ticket each time; add an airport to the route when it has no tickets left, then reverse.
-
Swim In Rising Water Hard
Water rises by 1 each second; find the earliest time you can swim from the top-left to the bottom-right.
Show answer
Technique: Dijkstra on the maximum along the path
The clue: Minimise the highest cell you must pass through.
The trick: Dijkstra where a path's cost is the largest height on it; pop cells in order of that cost.
-
Alien Dictionary Hard
Given words sorted in an unknown alphabet, work out the letter order.
Show answer
Technique: Build a graph + topological sort
The clue: An order between letters from comparisons = dependencies.
The trick: Compare neighbouring words at their first different letter to get an edge; topologically sort; watch for 'abc' before 'ab' (invalid).
What to say in the interview
'Because the edges have weights (or strict prerequisites), standard BFS is insufficient. I'll need to use Dijkstra's Algorithm (or Union-Find) to solve this optimally.'
Follow-up prep
Can Dijkstra's handle negative weights? (No, you'd need Bellman-Ford).