Practice Problems on 0-1 BFS Algorithm for Competitive Programming

0-1 BFS Algorithm for Competitive Programming

0-1 BFS Algorithm is a variation of simple BFS and is used to calculate Single vertex_source Shortest Path to all the nodes in a weighted graph provided the edges have weights 0 and 1 only. This algorithm runs in O(|E|) time which is much faster as compared to the Single Source Shortest Path Algorithms.

Similar Reads

Why to use 0-1 BFS Algorithm?

Using a simple BFS, we can find the minimum distance from a vertex_source node to all other nodes in O(|E|) time provided the graph is an unweighted graph or all the edges have the same weight. In case, the edges have different weights, then we can find the minimum distance to all nodes using Dijkstra’s Algorithm, Bellman-Ford or Shortest Path Faster Algorithm. But, if there is a constraint on the edge weights that they can only be 0 or 1, then applying the above-mentioned algorithms would be an overkill as Dijkstra’s Algorithm runs in O(|E| * log|V|) time and Bellman Ford and SPFA runs in O(|V| * |E|). So, if a graph has edges with weights 0 and 1 only, then we can calculate the minimum distance from a vertex_source node to all the other nodes in O(|E|) time using the 0-1 BFS Algorithm....

Idea behind 0-1 BFS Algorithm:

The idea of 0-1 BFS is similar to Dijkstra’s Algorithm. In the Dijkstra’s Algorithm, we maintain a priority queue or a Min Heap to keep track of all the nodes which can be relaxed in future to get the minimum distance. Initially, we push the vertex_source node with its distance as 0 and then pop it and push all its neighbors who can be relaxed in the future. We keep on doing the same till there is no node to relax further....

How to identify the problem based on 0-1 BFS Algorithm?

The problems based on 0-1 BFS Algorithm have one of the following patterns:...

Implementation of 0-1 BFS Algorithm:

C++ #include using namespace std; // Method to implement 0-1 BFS Algorithm void bfs_01(vector > >& graph, vector& dist, int vertex_source) { // Initializing the distance of vertex_source node // from itself as 0 dist[vertex_source] = 0; deque dq; dq.push_front(vertex_source); while (!dq.empty()) { int node = dq.front(); dq.pop_front(); // Checking all the neighbors for relaxation for (auto edge : graph[node]) { int childNode = edge.first; int weight = edge.second; // If the neighbor can be relaxed if (dist[childNode] > dist[node] + weight) { dist[childNode] = dist[node] + weight; // If the edge weight is 1, // push it at the back of deque if (weight) dq.push_back(childNode); // If the edge weight is 0, // push it at the front of deque else dq.push_front(childNode); } } } } int main() { // Inputs int V = 6, E = 7, vertex_source = 0; vector > > graph(V); vector > edges{ { 0, 1, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 0 }, { 5, 0, 0 }, { 1, 4, 1 } }; // Representing the graph as adjacent list for (auto edge : edges) { graph[edge[0]].push_back({ edge[1], edge[2] }); graph[edge[1]].push_back({ edge[0], edge[2] }); } // dist array to store distance of all nodes // from vertex_source node vector dist(V, 1e9); bfs_01(graph, dist, vertex_source); for (int i = 0; i < V; i++) cout << dist[i] << " "; return 0; } Java import java.util.ArrayDeque; import java.util.Deque; import java.util.LinkedList; import java.util.List; public class ZeroOneBFS { // Method to implement 0-1 BFS Algorithm static void bfs01(List> graph, int[] dist, int vertex_source) { // Initializing the distance of the vertex_source node // from itself as 0 dist[vertex_source] = 0; Deque deque = new LinkedList<>(); deque.addFirst(vertex_source); while (!deque.isEmpty()) { int node = deque.pollFirst(); // Checking all the neighbors for relaxation for (Pair edge : graph.get(node)) { int childNode = edge.first; int weight = edge.second; // If the neighbor can be relaxed if (dist[childNode] > dist[node] + weight) { dist[childNode] = dist[node] + weight; // If the edge weight is 1, // push it at the back of the deque if (weight == 1) deque.addLast(childNode); // If the edge weight is 0, // push it at the front of the deque else deque.addFirst(childNode); } } } } public static void main(String[] args) { // Inputs int V = 6, E = 7, vertex_source = 0; List> graph = new LinkedList<>(); List edges = List.of(new int[]{0, 1, 1}, new int[]{1, 2, 1}, new int[]{2, 3, 1}, new int[]{3, 4, 1}, new int[]{4, 5, 0}, new int[]{5, 0, 0}, new int[]{1, 4, 1}); // Representing the graph as an adjacency list for (int i = 0; i < V; i++) { graph.add(new LinkedList<>()); } for (int[] edge : edges) { graph.get(edge[0]).add(new Pair(edge[1], edge[2])); graph.get(edge[1]).add(new Pair(edge[0], edge[2])); } // dist array to store the distance of all nodes // from the vertex_source node int[] dist = new int[V]; for (int i = 0; i < V; i++) { dist[i] = (int) 1e9; } bfs01(graph, dist, vertex_source); for (int i = 0; i < V; i++) { System.out.print(dist[i] + " "); } } static class Pair { int first, second; Pair(int first, int second) { this.first = first; this.second = second; } } } // This code is contributed by rambabuguphka Python3 from collections import deque # Method to implement 0-1 BFS Algorithm def bfs_01(graph, dist, vertex_source): # Initializing the distance of vertex_source node # from itself as 0 dist[vertex_source] = 0 dq = deque() dq.appendleft(vertex_source) while dq: node = dq.popleft() # Checking all the neighbors for relaxation for edge in graph[node]: childNode, weight = edge # If the neighbor can be relaxed if dist[childNode] > dist[node] + weight: dist[childNode] = dist[node] + weight # If the edge weight is 1, # push it at the back of deque if weight: dq.append(childNode) # If the edge weight is 0, # push it at the front of deque else: dq.appendleft(childNode) # Inputs V = 6 E = 7 vertex_source = 0 graph = [[] for _ in range(V)] edges = [[0, 1, 1], [1, 2, 1], [2, 3, 1], [3, 4, 1], [4, 5, 0], [5, 0, 0], [1, 4, 1]] # Representing the graph as adjacent list for edge in edges: graph[edge[0]].append((edge[1], edge[2])) graph[edge[1]].append((edge[0], edge[2])) # dist array to store distance of all nodes # from vertex_source node dist = [float('inf')] * V bfs_01(graph, dist, vertex_source) for i in range(V): print(dist[i], end=" ") C# using System; using System.Collections.Generic; public class ZeroOneBFS { // Method to implement 0-1 BFS Algorithm static void BFS01(List> graph, int[] dist, int vertex_source) { // Initializing the distance of the vertex_source node // from itself as 0 dist[vertex_source] = 0; LinkedList deque = new LinkedList(); deque.AddLast(vertex_source); while (deque.Count > 0) { int node = deque.First.Value; deque.RemoveFirst(); // Checking all the neighbors for relaxation foreach (Pair edge in graph[node]) { int childNode = edge.first; int weight = edge.second; // If the neighbor can be relaxed if (dist[childNode] > dist[node] + weight) { dist[childNode] = dist[node] + weight; // If the edge weight is 1, // push it at the back of the deque if (weight == 1) deque.AddLast(childNode); // If the edge weight is 0, // push it at the front of the deque else deque.AddFirst(childNode); } } } } public static void Main(string[] args) { // Inputs int V = 6, vertex_source = 0; List> graph = new List>(); List edges = new List { new int[] {0, 1, 1}, new int[] {1, 2, 1}, new int[] {2, 3, 1}, new int[] {3, 4, 1}, new int[] {4, 5, 0}, new int[] {5, 0, 0}, new int[] {1, 4, 1} }; // Representing the graph as an adjacency list for (int i = 0; i < V; i++) { graph.Add(new List()); } foreach (int[] edge in edges) { graph[edge[0]].Add(new Pair(edge[1], edge[2])); graph[edge[1]].Add(new Pair(edge[0], edge[2])); } // dist array to store the distance of all nodes // from the vertex_source node int[] dist = new int[V]; for (int i = 0; i < V; i++) { dist[i] = int.MaxValue; } BFS01(graph, dist, vertex_source); for (int i = 0; i < V; i++) { Console.Write(dist[i] + " "); } } public class Pair { public int first, second; public Pair(int first, int second) { this.first = first; this.second = second; } } } Javascript // Method to implement 0-1 BFS Algorithm function bfs_01(graph, dist, vertex_source) { // Initializing the distance of vertex_source node // from itself as 0 dist[vertex_source] = 0; let dq = []; dq.push(vertex_source); while (dq.length > 0) { let node = dq.shift(); // Checking all the neighbors for relaxation for (let edge of graph[node]) { let childNode = edge[0]; let weight = edge[1]; if (dist[childNode] > dist[node] + weight) { dist[childNode] = dist[node] + weight; // If the edge weight is 1, // push it at the back of deque if (weight) { dq.push(childNode); } // If the edge weight is 0, // push it at the front of deque else { dq.unshift(childNode); } } } } } // Inputs let V = 6, E = 7, vertex_source = 0; let graph = Array.from({ length: V }, () => []); // Representing the graph as adjacent list let edges = [ [0, 1, 1], [1, 2, 1], [2, 3, 1], [3, 4, 1], [4, 5, 0], [5, 0, 0], [1, 4, 1] ]; for (let edge of edges) { graph[edge[0]].push([edge[1], edge[2]]); graph[edge[1]].push([edge[0], edge[2]]); } // dist array to store distance of all nodes // from vertex_source node let dist = Array(V).fill(1e9); bfs_01(graph, dist, vertex_source); for (let i = 0; i < V; i++) { process.stdout.write(dist[i] + " "); }...

Use case of 0-1 BFS Algorithm in Competitive Programming:

1. Minimum edges to reverse to make path from a source to a destination:...

Dial’s Algorithm:

We can also extend 0-1 BFS Algorithm for a graph having multiple weights until all the edge weights are less than W, where W is a small integer. We can maintain K buckets in the queue and start popping from the front of the queue. This way, we start moving from smaller weight buckets to larger weight buckets....

Practice Problems on 0-1 BFS Algorithm for Competitive Programming:

Problem Problem Link Minimum Cost to reach the end of the matrix Practice Now Minimize the number of turns needed to reach from top left cell to bottom right cell of the matrix Practice Now Count of Reachable cells in Grid within given Left-Right moves Practice Now Two Rats in a Maze Practice Now Minimum Jumps to move outside the matrix Practice Now...