Given a graph and the list of neighbours for each node in an array graph[] of size N, where graph[i] contains a list of neighbor nodes that are connected to ith node, the task is to visit all the nodes of the given graph in a minimum amount of time.
Note: Movement from any node to its neighbour takes one unit of time
Example:
Input: [[1, 2, 3], [2, 0], [0, 1], [0, 4], [3]]
Output: 4
Explanation:
One possible way to visit all node in minimum number of time is shown by the below graph![]()
Â
Input: [[1, 2, 3], [2, 0], [0, 1], [0]]
Output: 3
An approach using BFS + BitMasking:
Usually it is best to use BFS to find the minimum time problem in graph. However, in this case, we cannot use traditional BFS since traditional BFS can only visit the elements once. In this case, repetition is allowed, which means we can traverse any node multiple times, leading to an infinite loop. To handle infinite loop we can use Bitmasking to store the states while moving over graph.
Follow the step below to implement the above idea:
- Create an adjacency list from the given graph
- Initialize a variable finalMask = (1 << number_of_nodes)  – 1, this represent the state when all node has been visited.
- Initialize a variable timeCount = 0 to keep track of the minimum time to visit all nodes.
- Initialize a queue for BFS which will store the current node id and mask of visited nodes.
- Initialize a 2D array visited[][] for keeping track of nodes with all possible masks that are visited in the path.
- Push every node as a starting node for all possible paths with their mask for counting the number of the minimum time to visit all the node
- While the queue is not empty:
- Iterate over each level
- Fetch and pop the current node
- Check if the current node mask is equal to finalMask:
- If the condition is true, return timeCount as the result.
- Explore all the children of the current node:
- Make a new mask for the child by toggling the ith bit of the current Mask.
- If the new mask for the child has not been visited yet, push the child and new Mask in the queue and mark visited for the child with new mask.
- Increment the time Count after each level
- Iterate over each level
Below is the implementation of the above approach:
C++
// C++ code to implement the approach Â
#include <bits/stdc++.h> using namespace std; Â
// Function to calculate the minimum time int minimizeTime(vector<vector< int > >& graph) { Â Â Â Â long long n = graph.size(); Â
    // Create adjacency list from the given graph     vector<vector< long long > > adj(n); Â
    for ( int i = 0; i < n; i++) {         for ( auto j : graph[i]) { Â
            adj[i].push_back(j);         }     } Â
    // Final mask when all the node will be visited     long long finalMask = ( long long )(1 << n) - 1; Â
    // Initialize a queue for BFS which will store current     // node id and mask of visited nodes.     queue<pair< long long , long long > > q; Â
    // Initialize a visited array for keeping track     // of all mask that are visited in the path     vector<vector< bool > > visited(         n, vector< bool >(finalMask + 1)); Â
    // Push starting node for     // all possible path with their mask     for ( int i = 0; i < n; i++) {         q.push({ i, ( long long )(1 << i) });     } Â
    // For counting the minimum time     // to visit all the nodes     long long timeCount = 0; Â
    // Do while q.size > 0     while (q.size() > 0) {         int size = q.size(); Â
        // Iterate over each level         for ( int i = 0; i < size; i++) { Â
            // Fetch and pop the current node             auto curr = q.front();             q.pop(); Â
            // Check if the current node mask             // is equal to finalMask             if (curr.second == finalMask)                 return timeCount; Â
            // Explore all the child of current node             for ( auto child : adj[curr.first]) { Â
                // Make a new Mask for child                 long long newVisitedBit                     = curr.second | (1 << child); Â
                // If new Mask for child has                 // not been visited yet,                 // push child and new Mask in                 // the queue and mark visited                 // for child with newVisitedBit                 if (visited[child][newVisitedBit]                     == false ) { Â
                    q.push({ child, newVisitedBit });                     visited[child][newVisitedBit] = true ;                 }             }         } Â
        // Increment the time Count after each level         timeCount++;     } Â
    // If all node can't be visited     return -1; } Â
// Driver code int main() { Â Â Â Â vector<vector< int > > graph = { Â Â Â Â Â Â Â Â { 1, 2, 3 }, { 2, 0 }, { 0, 1 }, { 0, 4 }, { 3 } Â Â Â Â }; Â
    // Function call     int minTime = minimizeTime(graph);     cout << minTime << endl; Â
    return 0; } |
Java
// Java code to implement the approach import java.util.*; Â
// Pair class class Pair { Â Â Â Â int first, second; Â
    Pair( int first, int second)     {         this .first = first;         this .second = second;     } Â
    public int getKey() { return this .first; } Â
    public int getValue() { return this .second; } } Â
class GFG {     // Function to calculate the minimum time     public static int     minimizeTime(ArrayList<ArrayList<Integer> > graph)     {         int n = graph.size(); Â
        // Create adjacency list from the given graph         ArrayList<ArrayList<Integer> > adj             = new ArrayList<ArrayList<Integer> >(n); Â
        for ( int i = 0 ; i < n; i++) {             adj.add( new ArrayList<Integer>());             for ( int j : graph.get(i)) {                 adj.get(i).add(j);             }         } Â
        // Final mask when all the node will be visited         int finalMask = ( 1 << n) - 1 ; Â
        // Initialize a queue for BFS which will store         // current node id and mask of visited nodes.         Queue<Pair> q = new LinkedList<Pair>(); Â
        // Initialize a visited array for keeping track         // of all mask that are visited in the path         boolean [][] visited = new boolean [n][finalMask + 1 ]; Â
        // Push starting node for         // all possible path with their mask         for ( int i = 0 ; i < n; i++) {             q.add( new Pair(i, ( 1 << i)));         } Â
        // For counting the minimum time         // to visit all the nodes         int timeCount = 0 ; Â
        // Do while q.size > 0         while (q.size() > 0 ) {             int size = q.size(); Â
            // Iterate over each level             for ( int i = 0 ; i < size; i++) {                 // Fetch and pop the current node                 Pair curr = q.poll(); Â
                // Check if the current node mask                 // is equal to finalMask                 if (curr.getValue() == finalMask)                     return timeCount; Â
                // Explore all the child of current node                 for ( int child : adj.get(curr.getKey())) {                     // Make a new Mask for child                     int newVisitedBit                         = curr.getValue() | ( 1 << child); Â
                    // If new Mask for child has                     // not been visited yet,                     // push child and new Mask in                     // the queue and mark visited                     // for child with newVisitedBit                     if (visited[child][newVisitedBit]                         == false ) {                         q.add(                             new Pair(child, newVisitedBit));                         visited[child][newVisitedBit]                             = true ;                     }                 }             }             // Increment the time Count after each level             timeCount++;         }         // If all node can't be visited         return - 1 ;     } Â
    // Driver code     public static void main(String[] args)     {         ArrayList<ArrayList<Integer> > graph             = new ArrayList<ArrayList<Integer> >();         graph.add(             new ArrayList<Integer>(Arrays.asList( 1 , 2 , 3 )));         graph.add(             new ArrayList<Integer>(Arrays.asList( 2 , 0 )));         graph.add(             new ArrayList<Integer>(Arrays.asList( 0 , 1 )));         graph.add(             new ArrayList<Integer>(Arrays.asList( 0 , 4 )));         graph.add( new ArrayList<Integer>(Arrays.asList( 3 ))); Â
        // Function call         int minTime = minimizeTime(graph);         System.out.println(minTime);     } } Â
// This code is contributed by Tapesh(tapeshdua420) |
Python3
# Python code to implement the approach Â
# Function to calculate the minimum time def minimizeTime(graph):     n = len (graph)          # Create adjacency list from the given graph     adj = [[] for i in range (n)]          for i in range (n):         for j in graph[i]:             adj[i].append(j)          # Final mask when all the node will be visited     finalMask = ( 1 <<n) - 1          # Initialize a queue for BFS which will store current     # node id and mask of visited nodes.     q = []          # Initialize a visited array for keeping track     # of all mask that are visited in the path     visited = [[ 0 for i in range (finalMask + 1 )] for j in range (n)]          # Push starting node for     # all possible path with their mask     for i in range (n):         q.append([i, 1 <<i])          # For counting the minimum time     # to visit all the nodes     timeCount = 0          # Do while q.size > 0          while ( len (q) > 0 ):         size = len (q)                  # Iterate over each level         for i in range (size):                          # Fetch and pop the current node             curr = q.pop( 0 )                          # Check if the current node mask             # is equal to finalMask             if (curr[ 1 ] = = finalMask):                 return timeCount                          # Explore all the child of current node             for child in adj[curr[ 0 ]]:                                  # Make a new Mask for child                 newVisitedBit = curr[ 1 ]|( 1 <<child)                                  # If new Mask for child has                 # not been visited yet,                 # push child and new Mask in                 # the queue and mark visited                 # for child with newVisitedBit                 if (visited[child][newVisitedBit] = = False ):                     q.append([child,newVisitedBit])                     visited[child][newVisitedBit] = True                                   # Increment the time Count after each level         timeCount = timeCount + 1          # If all node can't be visited     return - 1      # Driver code graph = [[ 1 , 2 , 3 ],[ 2 , 0 ],[ 0 , 1 ],[ 0 , 4 ],[ 3 ]] Â
# Function calla minTime = minimizeTime(graph) print (minTime) Â
# This code is contributed by Pushpesh Raj. |
C#
// C# code to implement the approach using System; using System.Collections.Generic; Â
class Program {     // Driver code     static void Main( string [] args)     {         List<List< int > > graph = new List<List< int > >();         graph.Add( new List< int >( new int [] { 1, 2, 3 }));         graph.Add( new List< int >( new int [] { 2, 0 }));         graph.Add( new List< int >( new int [] { 0, 1 }));         graph.Add( new List< int >( new int [] { 0, 4 }));         graph.Add( new List< int >( new int [] { 3 })); Â
        // Function call         int minTime = minimizeTime(graph);         Console.WriteLine(minTime);     } Â
    // Function to calculate the minimum time     public static int minimizeTime(List<List< int > > graph)     {         int n = graph.Count; Â
        // Create adjacency list from the given graph         List<List< int > > adj = new List<List< int > >(n); Â
        for ( int i = 0; i < n; i++) {             adj.Add( new List< int >());             foreach ( int j in graph[i]) { adj[i].Add(j); }         } Â
        // Final mask when all the node will be visited         int finalMask = (1 << n) - 1; Â
        // Initialize a queue for BFS which will store         // current node id and mask of visited nodes.         Queue<Pair> q = new Queue<Pair>(); Â
        // Initialize a visited array for keeping track         // of all mask that are visited in the path         bool [, ] visited = new bool [n, finalMask + 1]; Â
        // Push starting node for         // all possible path with their mask         for ( int i = 0; i < n; i++) {             q.Enqueue( new Pair(i, (1 << i)));         } Â
        // For counting the minimum time         // to visit all the nodes         int timeCount = 0; Â
        // Do while q.size > 0         while (q.Count > 0) {             int size = q.Count; Â
            // Iterate over each level             for ( int i = 0; i < size; i++) {                 // Fetch and pop the current node                 Pair curr = q.Dequeue(); Â
                // Check if the current node mask                 // is equal to finalMask                 if (curr.getValue() == finalMask)                     return timeCount; Â
                // Explore all the child of current node                 foreach ( int child in adj[curr.getKey()])                 {                     // Make a new Mask for child                     int newVisitedBit                         = curr.getValue() | (1 << child); Â
                    // If new Mask for child has                     // not been visited yet,                     // push child and new Mask in                     // the queue and mark visited                     // for child with newVisitedBit                     if (visited[child, newVisitedBit]                         == false ) {                         q.Enqueue(                             new Pair(child, newVisitedBit));                         visited[child, newVisitedBit]                             = true ;                     }                 }             }             // Increment the time Count after each level             timeCount++;         }         // If all node can't be visited         return -1;     } } Â
// Pair class class Pair { Â Â Â Â public int first, second; Â
    public Pair( int first, int second)     {         this .first = first;         this .second = second;     } Â
    public int getKey() { return this .first; } Â
    public int getValue() { return this .second; } } Â
// This code is contributed by Tapesh(tapeshdua420) |
Javascript
// JavaScript code to implement the approach Â
// Function to calculate the minimum time function minimizeTime(graph){ Â Â Â Â var n = graph.length; Â
    // Create adjacency list from the given graph     var adj = [];     for ( var i=0;i<n;i++){         adj.push([]);         for ( var j=0;j<graph[i].length;j++){             adj[i].push(graph[i][j]);         }     } Â
    // Final mask when all the node will be visited     var finalMask = (1<<n) - 1; Â
    // Initialize a queue for BFS which will store current     // node id and mask of visited nodes.     var q = []; Â
    // Initialize a visited array for keeping track     // of all mask that are visited in the path     var visited = [];     for ( var i=0;i<n;i++){         visited.push([]);         for ( var j=0;j<=finalMask;j++){             visited[i].push(0);         }     } Â
    // Push starting node for     // all possible path with their mask     for ( var i=0;i<n;i++){         q.push([i,1<<i]);     } Â
    // For counting the minimum time     // to visit all the nodes     var timeCount = 0; Â
     // Do while q.size > 0     while (q.length > 0){         var size = q.length; Â
        // Iterate over each level         for ( var i=0;i<size;i++){ Â
            // Fetch and pop the current node             var curr = q.shift(); Â
            // Check if the current node mask             // is equal to finalMask             if (curr[1] == finalMask){                 return timeCount;             } Â
            // Explore all the child of current node             for ( var j=0;j<adj[curr[0]].length;j++){                 var child = adj[curr[0]][j]; Â
                // Make a new Mask for child                 var newVisitedBit = curr[1]|(1<<child); Â
                // If new Mask for child has                 // not been visited yet,                 // push child and new Mask in                 // the queue and mark visited                 // for child with newVisitedBit                 if (visited[child][newVisitedBit] == false ){                     q.push([child,newVisitedBit]);                     visited[child][newVisitedBit] = true ;                 }             }         } Â
        // Increment the time Count after each level         timeCount = timeCount + 1;     }     // If all node can't be visited     return -1; } Â
// Driver code var graph = [[1,2,3],[2,0],[0,1],[0,4],[3]]; Â
// Function call var minTime = minimizeTime(graph); console.log(minTime); Â
// This code is contributed by Tapesh(tapeshdua420). |
4
Time Complexity: O(V + E) where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V + E)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!