visited: BFS, DFS, and Dijkstra Explained Precisely
One of the most common sources of bugs in graph algorithms is marking a node as visited at the wrong time. This article explains exactly when and why nodes must be marked visited in BFS, DFS, and Dijkstra, based on their formal correctness invariants—not intuition or convention.
The timing of visited is not an implementation detail. It encodes what property of the node has become irreversible.
A node must be marked
visitedat the moment the algorithm’s guarantee becomes final.
Each algorithm has a different guarantee. Therefore, each marks visited at a different time.
visited MeansVisited = discovered
Once a node is discovered in BFS, the shortest path (in number of edges) to that node is already known.
A node must enter the queue at most once.
Mark visited when enqueuing, not when dequeuing.
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)visited MeansVisited = entered
Once DFS enters a node, re-entering it provides no new information and creates cycles.
A node must never be entered more than once along the active call stack.
Mark visited when entering the node (before recursion).
def dfs(node):
visited.add(node)
for n in node.neighbors:
if n not in visited:
visited MeansVisited = distance finalized
A node may be discovered multiple times with improving distances. visited means no further improvement is possible.
When a node is extracted as the global minimum from the priority queue, its shortest distance is final.
Mark visited when the node is popped from the priority queue.
while pq:
dist, u = heappop(pq)
if u in visited:
continue
visited.add(u)
for vIncorrect shortest paths.
Example:
A --10--> B
A --1--> C --1--> B
Early marking fixes B at distance 10 and blocks the optimal path of 2.
| Algorithm | Edge Weights | Meaning of visited | When to Mark |
|---|---|---|---|
| BFS | Equal | Discovered | Enqueue |
| DFS | Irrelevant | Entered | Entry / Push |
| Dijkstra | Non-negative | Distance finalized | Min-pop |
All three algorithms follow the same principle:
Mark a node visited when the algorithm’s correctness guarantee becomes irreversible.
If you cannot clearly state what property becomes final when you mark visited, the implementation is likely incorrect.
This is not a stylistic choice.
It is a correctness condition.