...

/

Unweighted Graphs: Breadth-First Search

Unweighted Graphs: Breadth-First Search

Learn about the breadth-first search algorithm and its applications in solving the shortest paths problem in unweighted graphs.

Implementation of breadth-first search

In the simplest special case of the shortest path problem, all edges have weight 1, and the length of a path is just the number of edges. This special case can be solved by a species of our generic graph-traversal algorithm called breadth-first search. Breadth-first search is often attributed to Edward Moore, who described it in 1957 (as “Algorithm A”) as the first published method to find the shortest path through a maze. Especially in the context of VLSI wiring and robot path planning, breadth-first search is sometimes attributed to Chin Yang Lee, who described several applications of Moore’s “Algorithm A” (with proper credit to Moore) in 1961. However, in 1945, more than a decade before Moore considered mazes, Konrad Zuse described an implementation of breadth-first search as a method to count and label the components of a disconnected graph.

Breadth-first search maintains a first-in-first-out queue of vertices, which initially contains only the source vertex s. At each iteration, the algorithm pulls a vertex uu from the front of the queue and examines each of its outgoing edges uvu\rightarrow v. Whenever the algorithm discovers an outgoing tense edge uvu\rightarrow v, it relaxes that edge and pushes vertex vv onto the queue. The algorithm ends when the queue becomes empty.

Algorithm


BFS(s)InitSSSP(s)Push(s)while the queue is not emptyuPull()for all edges uvif dist(v)>dist(u)+1<< if uv is tense >>dist(v)dist(u)+1pred(v)u<< relax uv >>Push(v)\underline{BFS(s)} \\ \hspace{0.4cm} InitSSSP(s) \\ \hspace{0.4cm} Push(s) \\ \hspace{0.4cm} while\space the\space queue\space is\space not\space empty \\ \hspace{1cm} u←Pull() \\ \hspace{1cm} for\space all\space edges\space u\rightarrow v \\ \hspace{1.7cm} if\space dist(v) > dist(u) + 1 \hspace{1cm} {\color{Red} \left< \left<\space if\space u\rightarrow v \space is\space tense \space \right > \right >} \\ \hspace{2.3cm} dist(v) ← dist(u) + 1 \\ \hspace{2.3cm} pred(v) ← u \hspace{2.1cm} {\color{Red} \left< \left<\space relax\space u\rightarrow v \space\right > \right >} \\ \hspace{2.3cm} Push(v)


Implementation

Press + to interact
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int INF = 1e9;
const int MAXN = 100005;
vector<int> adj[MAXN]; // adjacency list of the graph
int dist[MAXN], pred[MAXN];
bool visited[MAXN];
void InitSSSP(int s)
{
for (int i = 0; i < MAXN; i++)
{
dist[i] = INF;
pred[i] = -1;
visited[i] = false;
}
dist[s] = 0;
}
void Push(int s, queue<int> &q)
{
q.push(s);
visited[s] = true;
}
void BFS(int s)
{
InitSSSP(s);
queue<int> q;
Push(s, q);
while (!q.empty())
{
int u = q.front();
q.pop();
for (auto v: adj[u])
{
if (dist[v] > dist[u] + 1)
{
// u->v is tense
dist[v] = dist[u] + 1;
pred[v] = u; // relax u->v
if (!visited[v])
{
// add v to queue
Push(v, q);
}
}
}
}
}
int main()
{
// example usage
adj[1].push_back(2);
adj[1].push_back(3);
adj[2].push_back(4);
adj[3].push_back(4);
BFS(1);
for (int i = 1; i <= 4; i++)
{
cout << "Shortest distance from 1 to " << i << ": " << dist[i] << endl;
}
return 0;
}

Explanation

  • Line 6: Here, we have a constant integer variable named INF with a value of 1 billion.

  • Line 7: Here, we have a constant integer variable named MAXN with a value of 100005.

  • Line 13: The InitSSSP function initializes the distance, predecessor, and visited arrays for all nodes except the source node s.

  • Lines 13–23: The code first sets all the dist values to INF (infinity), all the pred values to -1, and all the visited values to false for every node in the graph. Then, it sets the dist value of the source node s to 0, as the distance from s to itself is 0.

  • Lines 25–29: The code pushes s onto the back of q, and it sets the boolean flag visited[s] to true. The reference to q is passed by non-const reference, which means that any changes made to q inside the function will affect the caller’s copy of q.

  • Lines 31–55: The BFS function performs a level-by-level traversal of the graph, updating the shortest path and predecessor arrays along the way, until all vertices have been explored.

Modifications of breadth-first search

Breadth-first search is somewhat easier to analyze if we break its execution into phases by introducing an imaginary token. Before we pull any vertices, we push the token into the queue. The current phase ends when we pull the token out of the queue; we begin the next phase when we push the token into the queue again. Thus, the first phase consists entirely of scanning the source vertex ss. The algorithm ends when the queue contains only the token. The modified algorithm is shown below, and the illustration shows an example of this algorithm in action. Let us emphasize that these modifications are merely a convenience for analysis; with or without the token, the algorithm pushes and pulls vertices in the same order, scans edges in the same order, and outputs exactly the same distances and predecessors.

Algorithm


...

Create a free account to access the full course.

By signing up, you agree to Educative's Terms of Service and Privacy Policy