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 ithnode, 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 graphInput: [[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++ 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 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) |
# 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# 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 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)