Program to find minimum number of roads we have to make to reach any city from first one in C++



Suppose we have two lists costs_from and costs_to of same size where each index i represents a city. It is making a one-way road from city i to j and their costs are costs_from[i] + costs_to[j]. We also have a list of edges where each edge contains [x, y] indicates there is already a one-way road from city x to y. If we want to go to any city from city 0, we have to find the minimum cost to build the necessary roads.

So, if the input is like costs_from = [6, 2, 2, 12] costs_to = [2, 2, 3, 2] edges = [[0, 3]], then the output will be 13, as we can go from 0 to 2 for a cost of 9. After that, we can go from 2 to 1 for a cost of 4. And we already have the road to go to 3 from 0. So total is 9 + 4 = 13.

To solve this, we will follow these steps −

  • n := size of costs_from
  • ret := 0
  • Define two maps edges and redges
  • for all item it in g:
    • insert it[1] at the end of edges[it[0]]
    • insert it[0] at the end of redges[it[1]]
  • from_cost := inf
  • Define one set visited and another set reachable
  • define a function dfs, this will take a number i
    • if i is not visited and i is not reachable, then:
      • insert i into visited
      • for all j in edges[i], do
        • dfs(j)
      • insert i at the end of po
  • define a function dfs2, this will take a number i
  • if i is visited, then
    • return true
  • if i is reachable
    • return false
  • mark i as visited and mark i as reachable
  • ret := true
  • for all j in redges[i], do
    • ret :+ ret AND dfs2(j)
  • return ret
  • Define one queue q
  • insert 0 into reachable and insert 0 into q
  • while (q is not empty), do:
    • node := first element of q
    • delete element from q
    • for each i in edges[node]
      • if i is not in reachable, then:
        • insert i into reachable, insert i into q
      • from_cost := minimum of from_cost and costs_from[node]
  • global_min := minimum element of costs_from
  • ret := ret + from_cost - global_min
  • Define an array po
  • for i in range 0 to n, do
    • dfs(i)
  • reverse the array po
  • for each i in po, do
    • if i is reachable, then:
      • go for next iteration
    • clear the visited array
    • initial := dfs2(i)
    • if initial is true, then:
      • best := inf
      • for each j in visited:
        • best := minimum of best and costs_to[j]
      • ret := ret + global_min + best
  • return ret

Let us see the following implementation to get better understanding −

Example

Live Demo

#include
using namespace std;
class Solution {
   public:
   int solve(vector& costs_from, vector& costs_to, vector>& g) {
      int n = costs_from.size();
      int ret = 0;
      map> edges;
      map> redges;
      for (auto& it : g) {
         edges[it[0]].push_back(it[1]);
         redges[it[1]].push_back(it[0]);
      }
      int from_cost = INT_MAX;
      set visited;
      set reachable;
      queue q;
      reachable.insert(0);
      q.push(0);
      while (!q.empty()) {
         int node = q.front();
         q.pop();
         for (int i : edges[node]) {
            if (!reachable.count(i)) {
               reachable.insert(i);
               q.push(i);
            }
         }
         from_cost = min(from_cost, costs_from[node]);
      }
      int global_min = *min_element(costs_from.begin(), costs_from.end());
      ret += from_cost - global_min;
      vector po;
      function dfs;
      dfs = [&](int i) {
         if (!visited.count(i) && !reachable.count(i)) {
            visited.insert(i);
            for (int j : edges[i]) {
               dfs(j);
            }
            po.push_back(i);
         }
      };
      for (int i = 0; i < n; i++) dfs(i);
      reverse(po.begin(), po.end());
      function dfs2;
      dfs2 = [&](int i) {
         if (visited.count(i)) return true;
         if (reachable.count(i)) return false;
         visited.insert(i);
         reachable.insert(i);
         bool ret = true;
         for (int j : redges[i]) {
            ret &= dfs2(j);
         }
         return ret;
      };
      for (int i : po) {
         if (reachable.count(i)) continue;
         visited.clear();
         bool initial = dfs2(i);
         if (initial) {
            int best = INT_MAX;
            for (int j : visited) {
               best = min(best, costs_to[j]);
            }
            ret += global_min + best;
         }
      }
      return ret;
   }
};

int solve(vector& costs_from, vector& costs_to, vector>& edges) {
   return (new Solution())->solve(costs_from, costs_to, edges);
}
int main(){
   vector costs_from = {6, 2, 2, 12};
   vector costs_to = {2, 2, 3, 2};
   vector> edges = {{0, 3}};
   cout << solve(costs_from, costs_to, edges);
}

Input

{6, 2, 2, 12}, {2, 2, 3, 2}, {{0, 3}}

Output

13

Advertisements