Open In App

Minimum time required by n cars to travel through all of the m roads

Improve
Improve
Like Article
Like
Save
Share
Report

Given m roads and n cars. The cars are numbered from 1 to n. You are also given an array arr[] of size m, each road has a value arr[i] – the index of a car that runs fast on this road. If a car is fast on a road, then it travels across the road in 1 hour, else it takes 2 hours (if not proficient) to travel through this road. Find out the minimum time required by these n cars to travel through all of these m roads. 

All cars run independently of each other and each car can run on a single road at once. All roads have the same length. 

Examples: 

Input:  N = 2, M = 4, arr[] = {1, 2, 1, 2}
Output: 2
Explanation: The first car will run on the 1st and 3rd roads and the Second car will be running on the 2nd and 4th roads. Both cars completed 2 roads in 2 hours as both are proficient in traveling their corresponding roads.

Input: N = 2, M = 4, arr[] = {1, 1, 1, 1}
Output: 3
Explanation: The first car will run on the 1st, 2nd, and 3rd roads, whereas the 4th road will be assigned to the 2nd car. The first car will be finishing his road in 3 hours, whereas the second car spends 2 hours (as the 2nd car is not proficient in traveling the 4th road).

Approach: The problem can be solved based on the following observation.

If you can use the cars in such a way that all roads can be traveled in time x, Then, you can complete all these roads using x + 1 or more time as well.

Follow the steps mentioned below to implement the idea:

  • As we are binary searching for the answer, we have to define the upper bound. 
  • In the Worst case, the total time can be 2 * m hours to travel through all roads. For example: if you assign all roads to a single car, and this car is not proficient in any of these roads.
  • To check whether all roads can be completed in the given time we will be creating a lambda function.
  • The function will be keeping track of free roads and needed roads. 
  • If the given time is greater than the total roads assigned to a car.
    • Add the extra time to the free roads slot.
  • Else, Add the left roads to the needed road.
  • In the end, if needed roads are greater than the free roads slot, Thus it is not possible to complete all of the roads in the given time amount.

Below is the Implementation of the above approach:

C++




// C++ code of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate minimum
// time required
void minTimeRequired(int n, int m, vector<int> arr)
{
 
    // cnt to count the total number of
    // road the ith car is proficient in
    vector<int> cnt(n + 1);
 
    // Calculating the total no. of
    // proficient roads that each
    // car can do
    for (int i = 0; i < m; i++)
 
        cnt[arr[i]]++;
 
    // Lambda function to check whether
    // given time is enough to complete
    // all m roads using n cars
    auto check = [&](int time) {
        long long free = 0, needed = 0;
 
        for (int i = 1; i <= n; i++) {
            if (time >= cnt[i]) {
 
                // Storing the number of
                // roads that can be done
                // if the provided time is
                // more than the number of
                // efficient roads assigned
                // to a car
                long long extraTime = (time - cnt[i]);
 
                // We are dividing the
                // difference by 2 because
                // as it is mentioned in the
                // question if the car is
                // not proficient then 2
                // sec are required to
                // complete a road.
                free += extraTime / 2;
            }
            else {
 
                // Storing the number of
                // roads that are left
                needed += cnt[i] - time;
            }
        }
 
        // If free road slots are greater
        // than or equal to the needed,
        // then it is possible to complete
        // all m roads in the given time
 
        return needed <= free;
    };
 
    // Maximum required time in worst
    // case is 2*m, if you assign all
    // roads to a single car, and this car
    // is not proficient in any of
    // these roads.
    int l = 0, r = 2 * m;
    int minTime = -1;
 
    // Binary Search on minTime
    while (l <= r) {
 
        int m = (l + r) / 2;
        if (check(m)) {
 
            // If we are able to complete
            // all roads using m unit of
            // time then check with lesser
            // time again
            minTime = m;
 
            r = m - 1;
        }
        else {
            l = m + 1;
        }
    }
 
    cout << minTime << '\n';
}
 
// Driver Code
int main()
{
    int n = 2, m = 4;
    vector<int> arr(m);
    arr = { 1, 2, 1, 2 };
 
    // Function call
    minTimeRequired(n, m, arr);
 
    return 0;
}


Java




// Java code of the above approach
import java.io.*;
import java.util.*;
import java.util.function.Function;
 
class GFG {
 
  // Function to calculate minimum time required
  static void minTimeRequired(int n, int m, int[] arr)
  {
 
    // cnt to count the total number of
    // road the ith car is proficient in
    int[] cnt = new int[n + 1];
 
    // Calculating the total no. of
    // proficient roads that each
    // car can do
    for (int i = 0; i < m; i++) {
      cnt[arr[i]]++;
    }
 
    Function<Integer, Boolean> check = (time) ->
    {
      long free = 0, needed = 0;
 
      for (int i = 1; i <= n; i++) {
        if (time >= cnt[i]) {
          // Storing the number of
          // roads that can be done
          // if the provided time is
          // more than the number of
          // efficient roads assigned
          // to a car
          long extraTime = (time - cnt[i]);
 
          // We are dividing the
          // difference by 2 because
          // as it is mentioned in the
          // question if the car is
          // not proficient then 2
          // sec are required to
          // complete a road.
          free += extraTime / 2;
        }
        else {
          // Storing the number of
          // roads that are left
          needed += cnt[i] - time;
        }
      }
 
      // If free road slots are greater
      // than or equal to the needed,
      // then it is possible to complete
      // all m roads in the given time
 
      return needed <= free;
    };
 
    // Maximum required time in worst
    // case is 2 * m, if you assign all
    // roads to a single car, and this car
    // is not proficient in any of
    // these roads.
    int l = 0, r = 2 * m;
    int minTime = -1;
 
    // Binary Search on minTime
    while (l <= r) {
      int mid = (l + r) / 2;
      if (check.apply(mid)) {
        // If we are able to complete
        // all roads using m unit of
        // time then check with lesser
        // time again
        minTime = mid;
 
        r = mid - 1;
      }
      else {
        l = mid + 1;
      }
    }
 
    System.out.println(minTime);
  }
 
  public static void main(String[] args)
  {
    int n = 2, m = 4;
    int[] arr = { 1, 2, 1, 2 };
 
    // Function call
    minTimeRequired(n, m, arr);
  }
}
 
// This code is contributed by lokeshmvs21.


Python3




# python3 code of the above approach
 
# Function to calculate minimum
# time required
 
 
def minTimeRequired(n, m, arr):
 
    # cnt to count the total number of
    # road the ith car is proficient in
    cnt = [0 for _ in range(n + 1)]
 
    # Calculating the total no. of
    # proficient roads that each
    # car can do
    for i in range(0, m):
 
        cnt[arr[i]] += 1
 
    # Lambda function to check whether
    # given time is enough to complete
    # all m roads using n cars
    def check(time):
        free = 0
        needed = 0
 
        for i in range(1, n+1):
            if (time >= cnt[i]):
 
                # Storing the number of
                # roads that can be done
                # if the provided time is
                # more than the number of
                # efficient roads assigned
                # to a car
                extraTime = (time - cnt[i])
 
                # We are dividing the
                # difference by 2 because
                # as it is mentioned in the
                # question if the car is
                # not proficient then 2
                # sec are required to
                # complete a road.
                free += extraTime // 2
 
            else:
 
                # Storing the number of
                # roads that are left
                needed += cnt[i] - time
 
        # If free road slots are greater
        # than or equal to the needed,
        # then it is possible to complete
        # all m roads in the given time
 
        return needed <= free
 
    # Maximum required time in worst
    # case is 2*m, if you assign all
    # roads to a single car, and this car
    # is not proficient in any of
    # these roads.
    l = 0
    r = 2 * m
    minTime = -1
 
    # Binary Search on minTime
    while (l <= r):
 
        m = (l + r) // 2
        if (check(m)):
 
            # If we are able to complete
            # all roads using m unit of
            # time then check with lesser
            # time again
            minTime = m
 
            r = m - 1
 
        else:
            l = m + 1
 
    print(minTime)
 
 
# Driver Code
if __name__ == "__main__":
 
    n = 2
    m = 4
    arr = [0 for _ in range(m)]
    arr = [1, 2, 1, 2]
 
    # Function call
    minTimeRequired(n, m, arr)
 
    # This code is contributed by rakeshsahni


C#




using System;
using System.Linq;
 
class Program
{
    static void Main(string[] args)
    {
        int n = 2, m = 4;
        int[] arr = { 1, 2, 1, 2 };
 
        // Function call
        MinTimeRequired(n, m, arr);
    }
 
    // Function to calculate minimum time required
    static void MinTimeRequired(int n, int m, int[] arr)
    {
        // cnt to count the total number of
        // roads the ith car is proficient in
        int[] cnt = new int[n + 1];
 
        // Calculating the total no. of
        // proficient roads that each
        // car can do
        for (int i = 0; i < m; i++)
        {
            cnt[arr[i]]++;
        }
 
        // Lambda function to check whether
        // given time is enough to complete
        // all m roads using n cars
        Func<int, bool> check = (time) =>
        {
            long free = 0, needed = 0;
 
            for (int i = 1; i <= n; i++)
            {
                if (time >= cnt[i])
                {
                    // Storing the number of
                    // roads that can be done
                    // if the provided time is
                    // more than the number of
                    // efficient roads assigned
                    // to a car
                    long extraTime = (time - cnt[i]);
 
                    // We are dividing the
                    // difference by 2 because
                    // as it is mentioned in the
                    // question if the car is
                    // not proficient then 2
                    // sec are required to
                    // complete a road.
                    free += extraTime / 2;
                }
                else
                {
                    // Storing the number of
                    // roads that are left
                    needed += cnt[i] - time;
                }
            }
 
            // If free road slots are greater
            // than or equal to the needed,
            // then it is possible to complete
            // all m roads in the given time
            return needed <= free;
        };
 
        // Maximum required time in worst
        // case is 2 * m, if you assign all
        // roads to a single car, and this car
        // is not proficient in any of
        // these roads.
        int l = 0, r = 2 * m;
        int minTime = -1;
 
        // Binary Search on minTime
        while (l <= r)
        {
            int mid = (l + r) / 2;
            if (check(mid))
            {
                // If we are able to complete
                // all roads using m unit of
                // time then check with lesser
                // time again
                minTime = mid;
 
                r = mid - 1;
            }
            else
            {
                l = mid + 1;
            }
        }
 
        Console.WriteLine(minTime);
    }
}


Javascript




// JavaScript code of the above approach
 
// Function to calculate minimum
// time required
function minTimeRequired(n, m, arr) {
 
// cnt to count the total number of
// road the ith car is proficient in
let cnt = new Array(n + 1).fill(0);
 
// Calculating the total no. of
// proficient roads that each
// car can do
for (let i = 0; i < m; i++) {
cnt[arr[i]]++;
}
 
// Lambda function to check whether
// given time is enough to complete
// all m roads using n cars
let check = (time) => {
let free = 0, needed = 0;
 
for (let i = 1; i <= n; i++) {
  if (time >= cnt[i]) {
 
    // Storing the number of
    // roads that can be done
    // if the provided time is
    // more than the number of
    // efficient roads assigned
    // to a car
    let extraTime = (time - cnt[i]);
 
    // We are dividing the
    // difference by 2 because
    // as it is mentioned in the
    // question if the car is
    // not proficient then 2
    // sec are required to
    // complete a road.
    free += Math.floor(extraTime / 2);
  }
  else {
 
    // Storing the number of
    // roads that are left
    needed += cnt[i] - time;
  }
}
 
// If free road slots are greater
// than or equal to the needed,
// then it is possible to complete
// all m roads in the given time
 
return needed <= free;
};
 
// Maximum required time in worst
// case is 2*m, if you assign all
// roads to a single car, and this car
// is not proficient in any of
// these roads.
let l = 0, r = 2 * m;
let minTime = -1;
 
// Binary Search on minTime
while (l <= r) {
 
let m = Math.floor((l + r) / 2);
if (check(m)) {
 
  // If we are able to complete
  // all roads using m unit of
  // time then check with lesser
  // time again
  minTime = m;
 
  r = m - 1;
}
else {
  l = m + 1;
}
}
 
console.log(minTime);
}
 
// Driver Code
let n = 2, m = 4;
let arr = [1, 2, 1, 2];
 
// Function call
minTimeRequired(n, m, arr);


Output

2

Time Complexity: O(n*logm)
Auxiliary Space: O(n)

Related Articles:



Last Updated : 22 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads