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.

Example :

C++
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

// Structure to represent an edge
struct Edge {
    int to;
    int weight;
};
// Function to add an edge to the graph
void addEdge(vector<vector<Edge> >& graph, int from, int to,
             int weight)
{
    graph[from].push_back({ to, weight });
}
// Function to perform 0-1 BFS algorithm
int zeroOneBFS(vector<vector<Edge> >& graph, int source,
               int destination)
{
    const int INF = 1e9;
    vector<int> distance(graph.size(), INF);
    deque<int> dq;
    // Push source node to the queue with distance 0
    dq.push_front(source);
    distance[source] = 0;
    // Loop until the queue is empty
    while (!dq.empty()) {
        int node = dq.front();
        dq.pop_front();
        // Traverse all adjacent nodes of the current node
        for (const Edge& edge : graph[node]) {
            int newDistance = distance[node] + edge.weight;
            if (newDistance < distance[edge.to]) {
                distance[edge.to] = newDistance;
                // If the weight of the edge is 0
                // push to the front of the queue
                if (edge.weight == 0) {
                    dq.push_front(edge.to);
                }
                // If the weight of the edge is 1
                // push to the back of the queue
                else {
                    dq.push_back(edge.to);
                }
            }
        }
    }
    // Return the distance to destination node
    return distance[destination];
}
int main()
{
    // Example usage
    int vertices = 5;
    vector<vector<Edge> > graph(vertices);
    // Add edges to the graph
    addEdge(graph, 0, 2, 0);
    addEdge(graph, 0, 2, 1);
    addEdge(graph, 1, 3, 0);
    addEdge(graph, 2, 3, 1);
    addEdge(graph, 3, 4, 0);
    // Find the minimum number of edges to reverse from node
    // 0 to node 4
    int source = 0, destination = 4;
    int minEdgesToReverse
        = zeroOneBFS(graph, source, destination);
    cout << minEdgesToReverse << endl;
    return 0;
}
Java
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

// Structure to represent an edge
class Edge {
    int to;
    int weight;

    public Edge(int to, int weight)
    {
        this.to = to;
        this.weight = weight;
    }
}

public class Main {
    // Function to add an edge to the graph
    public static void addEdge(List<List<Edge> > graph,
                               int from, int to, int weight)
    {
        graph.get(from).add(new Edge(to, weight));
    }

    // Function to perform 0-1 BFS algorithm
    public static int zeroOneBFS(List<List<Edge> > graph,
                                 int source,
                                 int destination)
    {
        final int INF = (int)1e9;
        int[] distance = new int[graph.size()];
        for (int i = 0; i < graph.size(); i++) {
            distance[i] = INF;
        }
        Deque<Integer> dq = new ArrayDeque<>();
        // Push source node to the queue with distance 0
        dq.offerFirst(source);
        distance[source] = 0;
        // Loop until the queue is empty
        while (!dq.isEmpty()) {
            int node = dq.pollFirst();
            // Traverse all adjacent nodes of the current
            // node
            for (Edge edge : graph.get(node)) {
                int newDistance
                    = distance[node] + edge.weight;
                if (newDistance < distance[edge.to]) {
                    distance[edge.to] = newDistance;
                    // If the weight of the edge is 0, push
                    // to the front of the queue
                    if (edge.weight == 0) {
                        dq.offerFirst(edge.to);
                    }
                    // If the weight of the edge is 1, push
                    // to the back of the queue
                    else {
                        dq.offerLast(edge.to);
                    }
                }
            }
        }
        // Return the distance to destination node
        return distance[destination];
    }

    public static void main(String[] args)
    {

        int vertices = 5;
        List<List<Edge> > graph = new ArrayList<>(vertices);
        for (int i = 0; i < vertices; i++) {
            graph.add(new ArrayList<>());
        }
        // Add edges to the graph
        addEdge(graph, 0, 2, 0);
        addEdge(graph, 0, 2, 1);
        addEdge(graph, 1, 3, 0);
        addEdge(graph, 2, 3, 1);
        addEdge(graph, 3, 4, 0);
        // Find the minimum number of edges to reverse from
        // node 0 to node 4
        int source = 0, destination = 4;
        int minEdgesToReverse
            = zeroOneBFS(graph, source, destination);
        System.out.println(minEdgesToReverse);
    }
}
Python3
from collections import deque

# Structure to represent an edge


class Edge:
    def __init__(self, to, weight):
        self.to = to
        self.weight = weight

# Function to add an edge to the graph


def addEdge(graph, fromNode, to, weight):
    graph[fromNode].append(Edge(to, weight))

# Function to perform 0-1 BFS algorithm


def zeroOneBFS(graph, source, destination):
    INF = int(1e9)
    distance = [INF] * len(graph)
    dq = deque()
    # Push source node to the queue with distance 0
    dq.appendleft(source)
    distance[source] = 0
    # Loop until the queue is empty
    while dq:
        node = dq.pop()
        # Traverse all adjacent nodes of the current node
        for edge in graph[node]:
            newDistance = distance[node] + edge.weight
            if newDistance < distance[edge.to]:
                distance[edge.to] = newDistance
                # If the weight of the edge is 0, push to the front of the queue
                if edge.weight == 0:
                    dq.appendleft(edge.to)
                # If the weight of the edge is 1, push to the back of the queue
                else:
                    dq.append(edge.to)
    # Return the distance to destination node
    return distance[destination]


# Example usage
vertices = 5
graph = [[] for _ in range(vertices)]
# Add edges to the graph
addEdge(graph, 0, 2, 0)
addEdge(graph, 0, 2, 1)
addEdge(graph, 1, 3, 0)
addEdge(graph, 2, 3, 1)
addEdge(graph, 3, 4, 0)
# Find the minimum number of edges to reverse from node 0 to node 4
source = 0
destination = 4
minEdgesToReverse = zeroOneBFS(graph, source, destination)
print(minEdgesToReverse)
# this code is contributed by Adarsh
JavaScript
// Define a class to represent an edge in the graph
class Edge {
    constructor(to, weight) {
        this.to = to; // Destination node of the edge
        this.weight = weight; // Weight of the edge (0 or 1)
    }
}

// Function to add an edge to the graph
function addEdge(graph, from, to, weight) {
    graph[from].push(new Edge(to, weight)); // Add a new edge to the adjacency list of the 'from' node
}

// Function to perform the 0-1 BFS algorithm
function zeroOneBFS(graph, source, destination) {
    const INF = 1e9; // Infinity value for representing unreachable distances
    const distance = new Array(graph.length).fill(INF); // Array to store distances from the source node
    const dq = []; // Deque (double-ended queue) for BFS traversal
    dq.push(source); // Push the source node to the deque
    distance[source] = 0; // Distance to the source node is 0
    
    // Loop until the deque is empty
    while (dq.length > 0) {
        const node = dq.shift(); // Remove the first node from the deque
        // Traverse all adjacent nodes of the current node
        for (const edge of graph[node]) {
            const newDistance = distance[node] + edge.weight; // Calculate the new distance to the adjacent node
            // Update the distance if the new distance is shorter
            if (newDistance < distance[edge.to]) {
                distance[edge.to] = newDistance; // Update the distance to the adjacent node
                // Push the adjacent node to the front or back of the deque based on the edge weight
                if (edge.weight === 0) {
                    dq.unshift(edge.to); // Push to the front of the deque if the edge weight is 0
                } else {
                    dq.push(edge.to); // Push to the back of the deque if the edge weight is 1
                }
            }
        }
    }
    
    // Return the distance to the destination node
    return distance[destination];
}

// Main function to execute the program
function main() {
    const vertices = 5; // Total number of vertices in the graph
    const graph = new Array(vertices).fill(null).map(() => []); // Initialize the adjacency list for the graph
    
    // Add edges to the graph
    addEdge(graph, 0, 2, 0);
    addEdge(graph, 0, 2, 1);
    addEdge(graph, 1, 3, 0);
    addEdge(graph, 2, 3, 1);
    addEdge(graph, 3, 4, 0);
    
    // Find the minimum number of edges to reverse from node 0 to node 4
    const source = 0, destination = 4; // Source and destination nodes for the BFS traversal
    const minEdgesToReverse = zeroOneBFS(graph, source, destination); // Perform 0-1 BFS algorithm
    console.log(minEdgesToReverse); // Output the result
}

// Call the main function to execute the program
main();
//This code is contributed by Prachi.

output :

1

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...