Who Goes First?

You have a DAG — no cycles, so a valid ordering exists. But which node do you process first?

In a small graph with 3 nodes, you can eyeball it. But what about a graph with 7 nodes and a web of dependencies? You need a systematic way to identify which nodes are ready — the ones you can process right now without violating any dependency.

Think about a university course schedule. Some courses have no prerequisites — you can take them in your first semester. Others require 2, 3, even 4 prior courses before you're eligible. The courses with zero prerequisites are your starting points. But here's the twist: once you complete a course, it might unlock others. Finishing Calculus I might be the last prerequisite someone needs for Physics II. That completion ripples outward.

The same thing happens in dependency graphs. Processing one node can make other nodes ready. The readiness state of the graph is dynamic — it changes with every node you process. The question isn't just “who goes first?” — it's "who goes first, and what does that unlock? And what does that unlock?"

This cascade of unlocking is the key to efficient ordering. If you can track it systematically, you never have to rescan the entire graph to find the next ready node. You just watch the neighbors of the node you just processed.

Let's find out how. You have 7 nodes in front of you. Which ones can go first?

Find the Ready Ones

Tap any node you think can go first. The graph will tell you if you're right — and show you exactly why if you're wrong.

Tap any node you think can go first.

What you just did is the most fundamental operation in dependency resolution: scanning for nodes with nothing blocking them. You weren't counting edges or computing numbers — you were looking at the shape of the graph and asking a simple question: “Does anything point at this node?”

When something did point at a node, you saw the blockers light up. That's the critical insight: a node isn't ready because of some intrinsic property. It's ready because of context. The same node could be ready in one graph and blocked in another, depending entirely on what points at it.

In a 7-node graph, visual scanning works. You can trace the arrows and find the unblocked nodes in a few seconds. But imagine a graph with 500 nodes. You couldn't visually scan for “no incoming edges” among 500 circles and thousands of arrows. You'd need a way to track each node's readiness as a number — a counter that starts at “how many things block this node” and ticks down as those blockers get processed.

You might already be forming a mental picture of that counter. You've been computing it intuitively every time you traced arrows to a node. The next screen makes the counting explicit — and shows you what happens to those counters when you remove a node from the graph.

The Ripple

You found the ready nodes. Now what? Processing a ready node doesn't just check it off a list — it changes the graph. Dependencies that pointed to the processed node are satisfied. Neighbors that were waiting lose one blocker.

Here's the question: when you process a ready node and remove it, which of its neighbors become newly ready? Not all of them will — some still have other blockers. Before the system shows you the ripple effect, you'll predict which nodes light up. The in-degree badges are hidden during your prediction. You'll need to trace the graph structure to figure it out.

After removing A, which nodes will become ready?

Processed
A

That cascade you just watched — one node removed, its neighbors' blockers dropping, some of them becoming newly ready — is the engine that drives every topological ordering algorithm. It's not a one-time event. It's a loop: process a ready node, update the graph, check for newly ready nodes, repeat.

Here's what makes the cascade so elegant: it's self-sustaining. As long as the graph is a DAG (and it is, because you proved that in Module A), the cascade never stalls. Processing a node always makes progress. Eventually some neighbor drops to zero blockers and becomes ready. The queue never permanently starves.

This ripple is also what makes topological sort efficient. You don't rescan the entire graph after each removal — you only check the neighbors of the removed node. In a sparse graph, that might be 2 or 3 nodes out of hundreds. The update is local, not global.

You've been running this cascade manually. But the computer needs a concrete number to track: how many blockers does each node currently have? That's coming next.

Spot the Liar

Every node in this graph has a label claiming how many things block it. But some labels are lying. If you trust them blindly, you'll process the wrong nodes first — violating dependencies and producing a broken ordering.

Your job: verify each label against the actual graph structure. Find the liars before they cause damage. For each liar you catch, you'll trace the real dependencies and see exactly what would go wrong if the algorithm trusted the false label.

These badges claim which nodes are ready. But some badges are LYING. Tap each “ready” node to verify.

This exercise might feel like a trick, but it mirrors something real. In distributed systems, cached values go stale. A build system's dependency cache might claim a file has no unresolved dependencies when it actually does — and the build breaks. A task scheduler might promote a job to “ready” when one of its upstream dependencies hasn't actually finished. The consequences are real: corrupted outputs, race conditions, crashes. The skill you just practiced — verifying computed values against ground truth by tracing actual structure — is exactly what debugging a stale cache or a misconfigured pipeline looks like.

More importantly, you now understand what the labels mean. A label of "0" doesn't mean a node is unimportant or isolated. It means every one of its dependencies has been satisfied. Nothing blocks it. And critically, a wrong label of "0" doesn't just produce wrong output — it causes the algorithm to process a node before its prerequisites are done. That's a dependency violation. In a build system, it means compiling a file before its dependencies exist. In a course schedule, it means enrolling a student in a class they're not prepared for.

A label of "2" means two specific dependencies haven't been resolved yet — and you can name them by tracing the arrows. The label isn't abstract. It corresponds to real, identifiable blockers.

The Name

You've been using this idea for three screens now. It has a name.

The number of incoming edges to a node is called its in-degree. A node's in-degree is the count of its direct dependencies — the number of things that must be completed before it can start.

In-degree zero doesn't mean “unimportant.” It means ready. Ready to process, ready to compile, ready to learn. Every incoming edge represents a dependency that hasn't been resolved yet. When all dependencies are resolved — when every incoming edge has been “consumed” by processing its source — the node's in-degree reaches zero. It's free.

Here's what makes in-degree powerful as a mechanism, not just a metric. Processing a ready node doesn't just complete one task — it decrements the in-degree of every node that was waiting for it. Some of those neighbors might hit zero. They become ready too. The cascade carries itself forward.

In an implementation, in-degree is just an array of integers:

1
const inDegree = new Array(n).fill(0);
2
for (const [from, to] of edges) {
3
  inDegree[to]++;
4
}

Each time you process a node, you loop through its outgoing edges and decrement: inDegree[neighbor]--. When a neighbor hits zero, it joins the queue of ready nodes.

0A0B1C2D1E2F2G
Tap green nodes (in-degree 0) to remove them

That loop — the one that decrements neighbors and checks for zero — is the ripple you watched on the previous screens. You were running it by visual inspection. The code just makes it mechanical.

This is the engine behind every topological sort algorithm. Not the initialization, not the output formatting — the engine. The part that does the work. The next module will formalize the full procedure and give it a name — but the core mechanism is the in-degree cascade, and you've already been running it for three screens. The formalization won't teach you anything new. It will just label what you already know.

Predict the Full Order

Time to put everything together. You'll see a graph with in-degree labels on every node. Study it for 5 seconds — memorize the structure, note the in-degrees. Then the labels disappear, and you'll predict the entire topological ordering from memory.

The graph edges stay visible. You can still trace connectivity. But the numbers are gone, so you'll need to reconstruct readiness from the graph structure itself — the skill you've been building for three screens.

Study the graph. Memorize which nodes are ready. Then you will predict the entire ordering.

5s

The code panel you just saw — the one that computes in-degree with a simple loop over edges — is doing exactly what you did by visual inspection during the study phase. You scanned each node, counted the arrows pointing at it, and mentally filed the number. The computer does the same thing, just faster and without forgetting.

But here's the difference between you and the code: you can reason about the structure. You know that removing a node with 3 outgoing edges will affect 3 neighbors. The code has to check each one. Your spatial intuition lets you predict cascades that the code discovers one step at a time.

That intuition is what separates someone who memorized the algorithm from someone who understands it. In the next module, you'll formalize everything you've been doing into a procedure with a name — and you'll discover you've been running it all along.

What You Learned

Three questions to test your understanding. These aren't about counting arrows — they're about reasoning through what happens when blockers are removed.

Removing All Blockers1/3
Part A

Remove all of C's predecessors from the graph.

A B