Minimum edge reversals to make a root - GeeksforGeeks

28 Nov, 2021
Given a directed tree with V vertices and V-1 edges, we need to choose such a root (from given nodes from where we can reach to every other node) with a minimum number of edge reversal. 
Examples:  
In above tree, if we choose node 3 as our 
root then we need to reverse minimum number
of 3 edges to reach every other node, 
changed tree is shown on the right side.
 
We can solve this problem using DFS. we start dfs at any random node of given tree and at each node we store its distance from starting node assuming all edges as undirected and we also store number of edges which need to be reversed in the path from starting node to current node, let’s denote such edges as back edges so back edges are those which point towards the node in a path. With this dfs, we also calculate total number of edge reversals in the tree. After this computation, at each node we can calculate ‘number of edge reversal to reach every other node’ as follows, Let total number of reversals in tree when some node is chosen as starting node for dfs is R then if we want to reach every other node from node i we need to reverse all back edges from path node i to starting node and we also need to reverse all other back edges other than node i to starting node path. First part will be (distance of node i from starting node – back edges count at node i) because we want to reverse edges in path from node i to starting node it will be total edges (i.e. distance) minus back edges from starting node to node i (i.e. back edge count at node i). The second part will be (total edge reversal or total back edges of tree R – back edge count of node i). After calculating this value at each node we will choose minimum of them as our result. 
In below code, in the given edge direction weight 0 is added and in reverse direction weight 1 is added which is used to count reversal edges in dfs method.
C++
Java
Python3
C#
Javascript
// C++ program to find min edge reversal to// make every node reachable from root#include <bits/stdc++.h>using namespace std;  // method to dfs in tree and populates disRev valuesint dfs(vector< pair<int, int> > g[],        pair<int, int> disRev[], bool visit[], int u){    // visit current node    visit[u] = true;    int totalRev = 0;      // looping over all neighbors    for (int i = 0; i < g[u].size(); i++)    {        int v = g[u][i].first;        if (!visit[v])        {            // distance of v will be one more than distance of u            disRev[v].first = disRev[u].first + 1;              // initialize back edge count same as            // parent node's count            disRev[v].second = disRev[u].second;              // if there is a reverse edge from u to i,            // then only update            if (g[u][i].second)            {                disRev[v].second = disRev[u].second + 1;                totalRev++;            }            totalRev += dfs(g, disRev, visit, v);        }    }      // return total reversal in subtree rooted at u    return totalRev;}  // method prints root and minimum number of edge reversalvoid printMinEdgeReverseForRootNode(int edges[][2], int e){    // number of nodes are one more than number of edges    int V = e + 1;      // data structure to store directed tree    vector< pair<int, int> > g[V];      // disRev stores two values - distance and back    // edge count from root node    pair<int, int> disRev[V];      bool visit[V];      int u, v;    for (int i = 0; i < e; i++)    {        u = edges[i][0];        v = edges[i][1];          // add 0 weight in direction of u to v        g[u].push_back(make_pair(v, 0));          // add 1 weight in reverse direction        g[v].push_back(make_pair(u, 1));    }      //    initialize all variables    for (int i = 0; i < V; i++)    {        visit[i] = false;        disRev[i].first = disRev[i].second = 0;    }      int root = 0;      // dfs populates disRev data structure and    // store total reverse edge counts    int totalRev = dfs(g, disRev, visit, root);      // UnComment below lines to print each node's    // distance and edge reversal count from root node    /*    for (int i = 0; i < V; i++)    {        cout << i << " : " << disRev[i].first              << " " << disRev[i].second << endl;    }    */      int res = INT_MAX;      // loop over all nodes to choose minimum edge reversal    for (int i = 0; i < V; i++)    {        // (reversal in path to i) + (reversal        // in all other tree parts)        int edgesToRev = (totalRev - disRev[i].second) +                         (disRev[i].first - disRev[i].second);          // choose minimum among all values        if (edgesToRev < res)        {            res = edgesToRev;            root = i;        }    }      // print the designated root and total    // edge reversal made    cout << root << " " << res << endl;}  // Driver code to test above methodsint main(){    int edges[][2] =    {        {0, 1},        {2, 1},        {3, 2},        {3, 4},        {5, 4},        {5, 6},        {7, 6}    };    int e = sizeof(edges) / sizeof(edges[0]);      printMinEdgeReverseForRootNode(edges, e);    return 0;}
// Java program to find min edge reversal to // make every node reachable from root import java.util.*;  class GFG{    // pair class    static class pair    {        int first,second;        pair(int a ,int b)        {            first = a;            second = b;        }    }  // method to dfs in tree and populates disRev values static int dfs(Vector<Vector< pair >> g,         pair disRev[], boolean visit[], int u) {     // visit current node     visit[u] = true;     int totalRev = 0;       // looping over all neighbors     for (int i = 0; i < g.get(u).size(); i++)     {         int v = g.get(u).get(i).first;         if (!visit[v])         {             // distance of v will be one more than distance of u             disRev[v].first = disRev[u].first + 1;               // initialize back edge count same as             // parent node's count             disRev[v].second = disRev[u].second;               // if there is a reverse edge from u to i,             // then only update             if (g.get(u).get(i).second!=0)             {                 disRev[v].second = disRev[u].second + 1;                 totalRev++;             }             totalRev += dfs(g, disRev, visit, v);         }     }       // return total reversal in subtree rooted at u     return totalRev; }   // method prints root and minimum number of edge reversal static void printMinEdgeReverseForRootNode(int edges[][], int e) {     // number of nodes are one more than number of edges     int V = e + 1;       // data structure to store directed tree     Vector<Vector< pair >> g=new Vector<Vector< pair >>();          for(int i = 0; i < V + 1; i++)    g.add(new Vector<pair>());      // disRev stores two values - distance and back     // edge count from root node     pair disRev[] = new pair[V];       for(int i = 0; i < V; i++)    disRev[i] = new pair(0, 0);          boolean visit[] = new boolean[V];       int u, v;     for (int i = 0; i < e; i++)     {         u = edges[i][0];         v = edges[i][1];           // add 0 weight in direction of u to v         g.get(u).add(new pair(v, 0));           // add 1 weight in reverse direction         g.get(v).add(new pair(u, 1));     }       // initialize all variables     for (int i = 0; i < V; i++)     {         visit[i] = false;         disRev[i].first = disRev[i].second = 0;     }       int root = 0;       // dfs populates disRev data structure and     // store total reverse edge counts     int totalRev = dfs(g, disRev, visit, root);       // UnComment below lines to print each node's     // distance and edge reversal count from root node     /*     for (int i = 0; i < V; i++)     {         cout << i << " : " << disRev[i].first             << " " << disRev[i].second << endl;     }     */      int res = Integer.MAX_VALUE;       // loop over all nodes to choose minimum edge reversal     for (int i = 0; i < V; i++)     {         // (reversal in path to i) + (reversal         // in all other tree parts)         int edgesToRev = (totalRev - disRev[i].second) +                         (disRev[i].first - disRev[i].second);           // choose minimum among all values         if (edgesToRev < res)         {             res = edgesToRev;             root = i;         }     }       // print the designated root and total     // edge reversal made     System.out.println(root + " " + res ); }   // Driver code public static void main(String args[]){     int edges[][] =     {         {0, 1},         {2, 1},         {3, 2},         {3, 4},         {5, 4},         {5, 6},         {7, 6}     };     int e = edges.length;       printMinEdgeReverseForRootNode(edges, e); }}   // This code is contributed by Arnab Kundu
# Python3 program to find min edge reversal# to make every node reachable from rootimport sys  # Method to dfs in tree and populates # disRev valuesdef dfs(g, disRev, visit, u):          # Visit current node    visit[u] = True    totalRev = 0      # Looping over all neighbors    for i in range(len(g[u])):        v = g[u][i][0]                  if (not visit[v]):                          # Distance of v will be one more            # than distance of u            disRev[v][0] = disRev[u][0] + 1              # Initialize back edge count same as            # parent node's count            disRev[v][1] = disRev[u][1]              # If there is a reverse edge from u to i,            # then only update            if (g[u][i][1]):                disRev[v][1] = disRev[u][1] + 1                totalRev += 1                              totalRev += dfs(g, disRev, visit, v)      # Return total reversal in subtree rooted at u    return totalRev  # Method prints root and minimum number of# edge reversaldef printMinEdgeReverseForRootNode(edges, e):          # Number of nodes are one more than    # number of edges    V = e + 1      # Data structure to store directed tree    g = [[] for i in range(V)]      # disRev stores two values - distance    # and back edge count from root node    disRev = [[0, 0] for i in range(V)]      visit = [False for i in range(V)]      # u, v    for i in range(e):        u = edges[i][0]        v = edges[i][1]                  # Add 0 weight in direction of u to v        g[u].append([v, 0])          # Add 1 weight in reverse direction        g[v].append([u, 1])      # Initialize all variables    for i in range(V):        visit[i] = False        disRev[i][0] = disRev[i][1] = 0      root = 0      # dfs populates disRev data structure and    # store total reverse edge counts    totalRev = dfs(g, disRev, visit, root)      # UnComment below lines to preach node's    # distance and edge reversal count from root node    # for (i = 0 i < V i++)    # {    #     cout << i << " : " << disRev[i][0]    #         << " " << disRev[i][1] << endl    # }    res = sys.maxsize      # Loop over all nodes to choose     # minimum edge reversal    for i in range(V):                  # (reversal in path to i) + (reversal        # in all other tree parts)        edgesToRev = ((totalRev - disRev[i][1]) +                   (disRev[i][0] - disRev[i][1]))          # Choose minimum among all values        if (edgesToRev < res):            res = edgesToRev            root = i      # Print the designated root and total    # edge reversal made    print(root, res)   # Driver code if __name__ == '__main__':          edges = [ [ 0, 1 ], [ 2, 1 ],              [ 3, 2 ], [ 3, 4 ],              [ 5, 4 ], [ 5, 6 ],              [ 7, 6 ] ]      e = len(edges)      printMinEdgeReverseForRootNode(edges, e)  # This code is contributed by mohit kumar 29
// C# program to find min edge reversal to // make every node reachable from rootusing System;using System.Collections.Generic;      class GFG{    // pair class    public class pair    {        public int first,second;        public pair(int a, int b)        {            first = a;            second = b;        }    }  // method to dfs in tree and populates disRev values static int dfs(List<List< pair >> g,                pair []disRev, Boolean []visit, int u) {     // visit current node     visit[u] = true;     int totalRev = 0;       // looping over all neighbors     for (int i = 0; i < g[u].Count; i++)     {         int v = g[u][i].first;         if (!visit[v])         {             // distance of v will be one more             // than distance of u             disRev[v].first = disRev[u].first + 1;               // initialize back edge count same as             // parent node's count             disRev[v].second = disRev[u].second;               // if there is a reverse edge from u to i,             // then only update             if (g[u][i].second != 0)             {                 disRev[v].second = disRev[u].second + 1;                 totalRev++;             }             totalRev += dfs(g, disRev, visit, v);         }     }       // return total reversal in subtree rooted at u     return totalRev; }   // method prints root and minimum number of edge reversal static void printMinEdgeReverseForRootNode(int [,]edges, int e) {     // number of nodes are one more than number of edges     int V = e + 1;       // data structure to store directed tree     List<List< pair >> g = new List<List< pair >>();          for(int i = 0; i < V + 1; i++)    g.Add(new List<pair>());      // disRev stores two values - distance and back     // edge count from root node     pair []disRev = new pair[V];       for(int i = 0; i < V; i++)    disRev[i] = new pair(0, 0);          Boolean []visit = new Boolean[V];       int u, v;     for (int i = 0; i < e; i++)     {         u = edges[i, 0];         v = edges[i, 1];           // add 0 weight in direction of u to v         g[u].Add(new pair(v, 0));           // add 1 weight in reverse direction         g[v].Add(new pair(u, 1));     }       // initialize all variables     for (int i = 0; i < V; i++)     {         visit[i] = false;         disRev[i].first = disRev[i].second = 0;     }       int root = 0;       // dfs populates disRev data structure and     // store total reverse edge counts     int totalRev = dfs(g, disRev, visit, root);       // UnComment below lines to print each node's     // distance and edge reversal count from root node     /*     for (int i = 0; i < V; i++)     {         cout << i << " : " << disRev[i].first             << " " << disRev[i].second << endl;     }     */      int res = int.MaxValue;       // loop over all nodes to choose minimum edge reversal     for (int i = 0; i < V; i++)     {         // (reversal in path to i) + (reversal         // in all other tree parts)         int edgesToRev = (totalRev - disRev[i].second) +                          (disRev[i].first - disRev[i].second);           // choose minimum among all values         if (edgesToRev < res)         {             res = edgesToRev;             root = i;         }     }       // print the designated root and total     // edge reversal made     Console.WriteLine(root + " " + res); }   // Driver code public static void Main(String []args){     int [,]edges = {{0, 1}, {2, 1},                     {3, 2}, {3, 4},                     {5, 4}, {5, 6},                     {7, 6}};     int e = edges.GetLength(0);       printMinEdgeReverseForRootNode(edges, e); }}   // This code is contributed by 29AjayKumar
<script>  // Javascript program to find min edge // reversal to make every node reachable // from rootclass pair{    constructor(a, b)    {        this.first = a;        this.second = b;    }}  // Method to dfs in tree and populates// disRev valuesfunction dfs(g, disRev, visit, u){          // Visit current node    visit[u] = true;    let totalRev = 0;       // Looping over all neighbors    for(let i = 0; i < g[u].length; i++)    {        let v = g[u][i].first;        if (!visit[v])        {                          // Distance of v will be one more            // than distance of u            disRev[v].first = disRev[u].first + 1;               // Initialize back edge count same as            // parent node's count            disRev[v].second = disRev[u].second;               // If there is a reverse edge from u to i,            // then only update            if (g[u][i].second != 0)            {                disRev[v].second = disRev[u].second + 1;                totalRev++;            }            totalRev += dfs(g, disRev, visit, v);        }    }       // Return total reversal in subtree     // rooted at u    return totalRev;}  // Method prints root and minimum number// of edge reversalfunction printMinEdgeReverseForRootNode(edges, e){          // Number of nodes are one more     // than number of edges    let V = e + 1;       // Data structure to store directed tree    let g = [];           for(let i = 0; i < V + 1; i++)        g.push([]);       // disRev stores two values - distance and     // back edge count from root node    let disRev = new Array(V);       for(let i = 0; i < V; i++)        disRev[i] = new pair(0, 0);           let visit = new Array(V);    let u, v;          for(let i = 0; i < e; i++)    {        u = edges[i][0];        v = edges[i][1];           // Add 0 weight in direction of u to v        g[u].push(new pair(v, 0));           // Add 1 weight in reverse direction        g[v].push(new pair(u, 1));    }       // Initialize all variables    for(let i = 0; i < V; i++)    {        visit[i] = false;        disRev[i].first = disRev[i].second = 0;    }       let root = 0;       // dfs populates disRev data structure and    // store total reverse edge counts    let totalRev = dfs(g, disRev, visit, root);       // UnComment below lines to print each node's    // distance and edge reversal count from root node    /*    for (int i = 0; i < V; i++)    {        cout << i << " : " << disRev[i].first            << " " << disRev[i].second << endl;    }    */    let res = Number.MAX_VALUE;       // Loop over all nodes to choose     // minimum edge reversal    for(let i = 0; i < V; i++)    {                  // (reversal in path to i) + (reversal        // in all other tree parts)        let edgesToRev = (totalRev - disRev[i].second) +                         (disRev[i].first - disRev[i].second);           // Choose minimum among all values        if (edgesToRev < res)        {            res = edgesToRev;            root = i;        }    }       // Print the designated root and total    // edge reversal made    document.write(root + " " + res );}  // Driver codelet edges = [ [ 0, 1 ], [ 2, 1 ],              [ 3, 2 ], [ 3, 4 ],              [ 5, 4 ], [ 5, 6 ],              [ 7, 6 ] ];  let e = edges.length;  printMinEdgeReverseForRootNode(edges, e);  // This code is contributed by rag2127  </script>
Output: 
3 3
This article is contributed by Utkarsh Trivedi. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
andrew1234
29AjayKumar
mohit kumar 29
rag2127
DFS
Graph
DFS
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Kruskal’s Minimum Spanning Tree Algorithm | Greedy Algo-2
Topological Sorting
Detect Cycle in a Directed Graph
Disjoint Set (Or Union-Find) | Set 1 (Detect Cycle in an Undirected Graph)
Ford-Fulkerson Algorithm for Maximum Flow Problem
Floyd Warshall Algorithm | DP-16
Bellman–Ford Algorithm | DP-23
Strongly Connected Components
Iterative Depth First Traversal of Graph
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)