← Back to section

Pattern 1: DFS and BFS with visited

The two traversals you already saw in Matrix and Tree now appear in their most general form. The only novelty compared to trees: since graphs have cycles, the visited set stops being optional β€” it is what prevents running forever.

🎯

Try it first: Number of Connected Components

Before reading the theory, try to solve it. You can start with brute force, you can fail β€” the point is to feel the problem. The theory comes right below.

There are n nodes (numbered from 0 to n-1) and a list of edges (undirected edges). Return the number of connected components (groups of nodes linked to each other).

Example: n = 5, edges = [[0,1],[1,2],[3,4]] β†’ 2 (the group {0,1,2} and the group {3,4}).

Carregando editor…

Tried it? The core idea: every time you find a node not yet visited, it starts a new group β€” and a search (DFS/BFS) from it marks the entire group. The theory below formalizes this.

The theory: traversing while marking visited

DFS (depth): go as deep as possible along a path, backing up when stuck. Recursive and short:

dfs(node):
    mark node as visited
    for each neighbor of node:
        if not visited: dfs(neighbor)

BFS (breadth): explore in layers, with a queue:

queue = [origin]; mark origin
while the queue is not empty:
    node = dequeue
    for each neighbor of node:
        if not visited: mark and enqueue

Both visit all reachable nodes from the origin, in O(V + E). The difference is the order (depth vs layers) β€” and the choice follows the same criterion as in Matrix: BFS for the shortest path; DFS for "reach / cover / exists". Compare the orders on the same graph:

ExecuΓ§Γ£o real, gravada passo a passo
Carregando Python no navegador (primeira vez demora alguns segundos)…
ExecuΓ§Γ£o real, gravada passo a passo
Carregando Python no navegador (primeira vez demora alguns segundos)…

Counting connected components

A graph can have several disconnected "pieces". To count them: traverse all nodes; each node still not visited starts a new component (+1), and a search from it marks the whole piece. It is the same reasoning as "counting islands" (Matrix!), now on a general graph. O(V + E) time.

Example: Clone Graph (DFS with a map)

"Copy an entire graph (nodes and edges), creating new objects." The challenge: when following the edges, you run into nodes already copied (because of cycles) β€” and you cannot copy them again. The solution: a map original β†’ copy, and registering the copy before recursing into the neighbors (otherwise, a cycle causes infinite recursion):

Carregando editor…

The map serves two purposes at once: memory of what was already cloned (avoids duplicating) and visited detector (avoids the infinite cycle). Changing the original afterwards proves that the copy is truly independent.

🧠 Review quiz

0/4

1. Why is the visited set MANDATORY in graphs, but was not in trees?

2. To count connected components, what is the strategy?

3. In Clone Graph, why register the copy in the map BEFORE recursing into the neighbors?

4. DFS and BFS on a graph visit the same nodes. How to choose between them?

Summary

  • DFS (depth, recursion) and BFS (layers, queue) traverse what is reachable in O(V+E), always with visited.
  • Connected components: each not-visited node starts a search = +1 component.
  • Clone Graph: map original β†’ copy registers before recursing (cuts cycles and avoids duplicating).

Next lesson: ordering tasks with dependencies β€” topological sort.