BFS & DFS
Breadth-first and depth-first search are the two ways to explore a graph from a starting node. Both visit every reachable node in O(n + m); BFS also finds the fewest hops.
Both searches keep a list of places to go and a record of where they've been
To explore a graph from one node, you need two things: the nodes you have found but not explored yet, and a record of every node already found, so a loop in the graph can't send you round forever. Take a node from the first, look at its neighbors, add the new ones to both, and repeat until nothing is left to explore.
The only real choice is which found node to explore next. Take the oldest, with a queue, and you get breadth-first search (BFS): it spreads out evenly, one ring of distance at a time. Take the newest, with a stack (or with recursion, which uses the call stack), and you get depth-first search (DFS): it follows one route as far as it goes before backing up.
The rule
Mark a node as seen when you first find it, and explore each node once. Then BFS and DFS both cost O(n + m) for n nodes and m links: every node is taken once, and every neighbor list is read once.
BFS explores in rings, so it finds the fewest hops
BFS starts with the start node in a queue. Each node it takes from the front gives its unseen neighbors a distance one larger than its own and sends them to the back. Since the queue is first in, first out, every node 1 hop away is taken before any node 2 hops away, and so on.
That ring order is why BFS finds shortest routes when every link counts the same: the first time it reaches a node is along a route with the fewest hops. Once links carry different weights, hop counts are no longer enough, and you need Dijkstra's algorithm.
DFS goes as deep as it can, then backs up
DFS is natural to write with recursion: visiting a node means marking it, then visiting each unseen neighbor in turn. The call stack remembers the route back. Here the rooms are nodes and each key is a directed link; the question is whether room 0 reaches every room.
Room 5 was never entered: nobody holds its key. DFS reaches exactly what BFS would, in a different order. The recursion is as deep as the longest route it follows, so a graph shaped like a long chain of 100,000 nodes can overflow the call stack. Then write it with your own stack: push the start, and each round pop a node and push its unseen neighbors.
An outer loop over every node finds every connected component
One search only reaches the nodes connected to its start. A connected component is a largest group of nodes that can all reach each other; an undirected graph splits into one or more of them. To find them all, loop over every node and start a new search from each one not yet seen: each search marks one whole component.
This problem then asks which components are complete, with every pair linked. A complete component of k nodes has k × (k − 1) ÷ 2 links, so its neighbor lists hold k × (k − 1) entries in all.
The searches never overlap, because a seen node is never explored again. So the whole loop still costs O(n + m), however many components there are.
Use BFS for fewest hops, DFS for anything about whole routes
BFS | DFS | |
|---|---|---|
Explores next | The oldest found node (a queue) | The newest found node (a stack or recursion) |
Order | Ring by ring, by distance from the start | One route to its end, then back up |
Finds | Fewest hops to every node | Reachability, components, every route, cycles |
Memory | The widest ring | The longest route |
Time | O(n + m) | O(n + m) |
For "can I get there?" and "how many groups?" either works, and DFS is usually shorter to write. For "how few steps?", use BFS. The next page applies both to boards of cells, where the neighbors are the cells next door.
3 questions
Remember this
- BFS and DFS both mark nodes as seen and explore each once: O(n + m).
- BFS takes the oldest found node from a queue, so it explores in rings and finds the fewest hops.
- DFS follows one route as deep as it goes, by recursion or with an explicit stack.
- Looping over every node and searching from each unseen one finds every connected component.
Now solve some yourself
Only this topic 0 of 11 solved
- EasyIs there a route between two nodes?
- MediumCount groups of friends from a matrix
- MediumFewest computers on a message route
- MediumFewest presses of double and minus one
- MediumSignposts that lead every room to the exit fastest
- MediumJump left or right to reach a zero
- MediumFind a round trip through cities
- MediumTurn the fewest one-way roads toward city 0
- MediumPairs of nodes that can't reach each other
- MediumFewest hops when link colors must alternate
- MediumBombs that set each other off
Mixed with topics you have practiced 0 unlocked
7 more once you have practiced Recursion & backtracking, Hash tables & maps. Play one of its examples to the end and solve one of its problems to unlock them.
Problems open on their own sites (LeetCode, Codeforces, CodeChef, AtCoder, CSES) in a new tab. Tick Solved when you get it accepted there; your ticks decide which mixed problems open next.
Next