BFS on General Graphs
BFS (Breadth-First Search) is a graph traversal like DFS, but it explores nodes in layers based on distance from a start node.
BFS is like “visit everything 1 step away, then 2 steps away, then 3 steps away…”
What BFS is used for
BFS is the go-to tool for:
- Shortest path in an unweighted graph (each edge cost = 1)
- Minimum number of edges from a start node to all nodes
- Checking connectivity / components
The key guarantee:
In an unweighted graph, BFS finds the shortest distance (fewest edges) from the start node to every reachable node.
Core idea: a queue + visited / distance
BFS uses a queue so nodes are processed in the same order they were discovered.
Maintain:
dist[v] =shortest number of edges from start tov(-1means “not visited yet”)
Process:
Put the start node in the queue, set
dist[start] = 0Pop a node
vFor each neighbor
to:- if it’s unvisited, set
dist[to] = dist[v] + 1 - push it into the queue
- if it’s unvisited, set
Because the queue processes earlier layers first, the first time you visit a node is guaranteed to be via the shortest path.
Implementation
Assume adjacency list:
int n;
vector<int> g[n];BFS from a single source:
vector<int> dist(n, -1);
queue<int> q;
int s = 0;
dist[s] = 0;
q.push(s);
while (!q.empty()) {
int v = q.front(); q.pop();
for (int to : g[v]) {
if (dist[to] != -1) continue; // already visited
dist[to] = dist[v] + 1;
q.push(to);
}
}Now dist[v] is:
0for the start node1for nodes one edge away2for nodes two edges away- etc.
-1if unreachable froms
BFS “layers” intuition (why shortest paths work)
When BFS runs:
- the queue first contains all nodes at distance 0
- then it grows with all nodes at distance 1
- then all nodes at distance 2
- …
So if to is discovered from v, the first time you set dist[to] it must be dist[v] + 1, and v is already the earliest possible layer that could reach it.
That’s why BFS gives shortest paths in unweighted graphs.
Getting the actual shortest path (not just distance)
Store parent[to] when you discover to.
vector<int> dist(n, -1), parent(n, -1);
queue<int> q;
int s = 0;
dist[s] = 0;
q.push(s);
while (!q.empty()) {
int v = q.front(); q.pop();
for (int to : g[v]) {
if (dist[to] != -1) continue;
dist[to] = dist[v] + 1;
parent[to] = v;
q.push(to);
}
}Reconstruct path from s to t:
vector<int> path;
int t = 7;
if (dist[t] != -1) {
for (int v = t; v != -1; v = parent[v]) path.push_back(v);
reverse(path.begin(), path.end());
}BFS vs DFS (practical difference)
DFS is great for:
- exploring structure
- detecting cycles
- connected components
- topological sorting (directed acyclic graphs)
BFS is great for:
- shortest paths in unweighted graphs
- “minimum steps” problems
- level-by-level exploration
Quick summary
- BFS uses a queue
- Visits nodes in increasing distance from the start
- Gives shortest path lengths in unweighted graphs
- With
parent[], you can reconstruct the shortest path