Find Eventual Safe States
Peel dead ends backward: a node is safe once every node it points to is already safe
Checking every path from a node would be exponential, but the question is really the opposite of Course Schedule's: instead of counting arrows IN and peeling from the sources, count arrows OUT and peel from the dead ends. A node with 0 outgoing edges is safe for free. Once every node IT points to is confirmed safe, it becomes safe too — so 'confirmed safe' spreads backward along the arrows exactly like 'no prerequisites left' spread forward. Whatever never gets reached is stuck feeding a cycle.
Details
Animated on: 6 nodes with moves 0->1, 0->2, 1->2, 1->3, 2->5, 3->0, 4->5 (a->b means a can move to b) — which nodes are eventually safe (every path from them dead-ends)?
Problem:Find Eventual Safe StatesMedium
Pattern:Topological Sort
Peel dead ends backward: a node is safe once every node it points to is already safe
step 1 / 10
Nodes and their moves
6 nodes, and an arrow a to b means a can move to b. A node is safe only if EVERY path out of it eventually dead-ends at a node with no outgoing edges — one arrow into a cycle is enough to disqualify it, so the question is which nodes can reach one.
1FUNCTION eventualSafeNodes(n, edges):2 FOR EACH (a, b) IN edges3 APPEND b TO adj[a]4 APPEND a TO radj[b]5 outdeg[a] <- outdeg[a] + 16 queue <- EVERY u WHERE outdeg[u] = 07 WHILE queue NOT EMPTY8 u <- REMOVE FIRST FROM queue9 safe[u] <- TRUE10 FOR EACH p IN radj[u]11 outdeg[p] <- outdeg[p] - 112 IF outdeg[p] = 013 APPEND p TO queue14 RETURN SORT(EVERY u WHERE safe[u])
← / → step · space play · Home restart
Every step in words
Show all 10 steps
- 6 nodes, and an arrow a to b means a can move to b. A node is safe only if EVERY path out of it eventually dead-ends at a node with no outgoing edges — one arrow into a cycle is enough to disqualify it, so the question is which nodes can reach one.
- Count the arrows leaving each node: 0 has 2, 1 has 2, 2 has 1, 3 has 1, 4 has 1, 5 has 0. A node with 0 is a dead end already — automatically safe — so that count is the only state worth tracking, same trick as counting arrows IN for a topological sort, just pointed the other way.
- Only node 5 has 0 outgoing edges — it is a dead end, so it is safe by definition. Queue it as the one confirmed-safe node to start peeling backward from.
- Node 5 comes off the queue with 0 edges outstanding, so mark it SAFE — that is 1 confirmed so far, and the queue is now empty.
- Every node that points AT 5 just had one of its own paths confirmed safe, so their counts drop by one: 2 now has 0, 4 now has 0. 2 and 4 reached 0, so they join the queue.
- Node 2 comes off the queue with 0 edges outstanding, so mark it SAFE — that is 2 confirmed so far, and 4 still waits.
- Every node that points AT 2 just had one of its own paths confirmed safe, so their counts drop by one: 0 now has 1, 1 now has 1. None of them reached 0, so nothing new is confirmed yet.
- Node 4 comes off the queue with 0 edges outstanding, so mark it SAFE — that is 3 confirmed so far, and the queue is now empty.
- Nothing points at 4, so no other node's count moves.
- The queue emptied with 2, 4, 5 confirmed safe, but 0, 1, 3 still carry a count above 0 — the highlighted arrows show why: they only ever lead back into each other, so none of THEM can ever be the one that dead-ends. RETURN [2, 4, 5].
Now solve it yourself
Watching is the first half. The second is writing it without the animation.