Open In App

Roots of a tree which give minimum height

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given an undirected graph, which has tree characteristics. It is possible to choose any node as root, the task is to find those nodes only which minimize the height of tree. 

Example: 
In below diagram all node are made as root one by one, we can see that when 3 and 4 are root, height of tree is minimum(2) so {3, 4} is our answer. 
 

We can solve this problem by first thinking about the 1-D solution, that is if the longest graph is given, then the node which will minimize the height will be mid node if total node count is odd or mid-two-node if total node count is even. This solution can be reached by the following approach – Start two pointers from both ends of the path and move one step each time until pointers meet or one step away, at the end pointers will be at those nodes which will minimize the height because we have divided the nodes evenly so the height will be minimum. 

The same approach can be applied to a general tree also. Start pointers from all leaf nodes and move one step inside each time, keep combining pointers which overlap while moving, at the end only one pointer will remain on some vertex or two pointers will remain at one distance away. Those nodes represent the root of the vertex which will minimize the height of the tree. 

So we can have only one root or at max two roots for minimum height depending on tree structure as explained above. For the implementation we will not use actual pointers instead we’ll follow BFS like approach, In starting all leaf node are pushed into the queue, then they are removed from the tree, next new leaf node is pushed in the queue, this procedure keeps on going until we have only 1 or 2 node in our tree, which represent the result. 

Implementation:

C++




//  C++ program to find root which gives minimum height to tree
#include <bits/stdc++.h>
using namespace std;
 
// This class represents a undirected graph using adjacency list
// representation
class Graph
{
public:
    int V; // No. of vertices
 
    // Pointer to an array containing adjacency lists
    list<int> *adj;
 
    // Vector which stores degree of all vertices
    vector<int> degree;
 
    Graph(int V);            // Constructor
    void addEdge(int v, int w);   // To add an edge
 
    // function to get roots which give minimum height
    vector<int> rootForMinimumHeight();
};
 
// Constructor of graph, initializes adjacency list and
// degree vector
Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
    for (int i = 0; i < V; i++)
        degree.push_back(0);
}
 
// addEdge method adds vertex to adjacency list and increases
// degree by 1
void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w);    // Add w to v’s list
    adj[w].push_back(v);    // Add v to w’s list
    degree[v]++;            // increment degree of v by 1
    degree[w]++;            // increment degree of w by 1
}
 
//  Method to return roots which gives minimum height to tree
vector<int> Graph::rootForMinimumHeight()
{
    queue<int> q;
 
    //  first enqueue all leaf nodes in queue
    for (int i = 0; i < V; i++)
        if (degree[i] == 1)
            q.push(i);
 
    //  loop until total vertex remains less than 2
    while (V > 2)
    {
        int popEle = q.size();
        V -= popEle;      // popEle number of vertices will be popped
         
        for (int i = 0; i < popEle; i++)
        {
            int t = q.front();
            q.pop();
 
            // for each neighbour, decrease its degree and
            // if it become leaf, insert into queue
            for (auto j = adj[t].begin(); j != adj[t].end(); j++)
            {
                degree[*j]--;
                if (degree[*j] == 1)
                    q.push(*j);
            }
        }
    }
 
    //  copying the result from queue to result vector
    vector<int> res;
    while (!q.empty())
    {
        res.push_back(q.front());
        q.pop();
    }
    return res;
}
 
 
//  Driver code
int main()
{
    Graph g(6);
    g.addEdge(0, 3);
    g.addEdge(1, 3);
    g.addEdge(2, 3);
    g.addEdge(4, 3);
    g.addEdge(5, 4);
 
      // Function Call
    vector<int> res = g.rootForMinimumHeight();
    for (int i = 0; i < res.size(); i++)
        cout << res[i] << " ";
    cout << endl;
}


Java




// Java program to find root which gives minimum height to
// tree
import java.io.*;
import java.util.*;
 
// This class represents a undirected graph using adjacency
// list representation
class Graph {
  private int V; // No. of vertices
 
  // Pointer to an array containing adjacency lists
  private LinkedList<Integer>[] adj;
 
  // List which stores degree of all vertices
  private int[] degree;
 
  @SuppressWarnings("unchecked")
  public Graph(int v) // Constructor
  {
    V = v;
    adj = new LinkedList[v];
    degree = new int[v];
    for (int i = 0; i < v; i++) {
      adj[i] = new LinkedList<Integer>();
    }
  }
 
  public void addEdge(int v, int w) // To add an edge
  {
    adj[v].add(w); // Add w to v’s list
    adj[w].add(v); // Add v to w’s list
    degree[v]++; // increment degree of v by 1
    degree[w]++; // increment degree of w by 1
  }
 
  // function to get roots which give minimum height
  public LinkedList<Integer> rootForMinimumHeight()
  {
    Queue<Integer> q = new LinkedList<>();
 
    // first enqueue all leaf nodes in queue
    for (int i = 0; i < V; i++) {
      if (degree[i] == 1)
        q.add(i);
    }
 
    // loop until total vertex remains less than 2
    while (V > 2) {
      int popEle = q.size();
      V -= popEle; // popEle number of vertices will
      // be popped
 
      for (int i = 0; i < popEle; i++) {
        int t = q.poll();
 
        // for each neighbour, decrease its degree
        // and if it become leaf, insert into queue
        for (int j : adj[t]) {
          degree[j]--;
          if (degree[j] == 1)
            q.add(j);
        }
      }
    }
 
    // copying the result from queue to result List
    LinkedList<Integer> res = new LinkedList<Integer>();
    while (!q.isEmpty()) {
      res.add(q.poll());
    }
    return res;
  }
}
 
public class GFG {
  // Driver code
  public static void main(String[] args)
  {
    Graph g = new Graph(6);
    g.addEdge(0, 3);
    g.addEdge(1, 3);
    g.addEdge(2, 3);
    g.addEdge(4, 3);
    g.addEdge(5, 4);
 
    // Function Call
    LinkedList<Integer> res = g.rootForMinimumHeight();
    for (int i : res)
      System.out.print(i + " ");
    System.out.println();
  }
}
 
// This code is contributed by cavi4762.


Python3




# Python program to find root which gives minimum
# height to tree
 
# This class represents a undirected graph using
# adjacency list representation
 
 
class Graph:
 
    # Constructor of graph, initialize adjacency list
    # and degree vector
    def __init__(self, V, addEdge, rootForMinimumHeight):
        self.V = V
        self.adj = dict((i, []) for i in range(V))
        self.degree = list()
        for i in range(V):
            self.degree.append(0)
 
        # The below lines allows us define methods outside
        # of class definition
        # Check http://bit.ly/2e5HfrW for better explanation
        Graph.addEdge = addEdge
        Graph.rootForMinimumHeight = rootForMinimumHeight
 
 
# addEdge method adds vertex to adjacency list and
# increases degree by 1
def addEdge(self, v, w):
    self.adj[v].append(w)  # Adds w to v's list
    self.adj[w].append(v)  # Adds v to w's list
    self.degree[v] += 1      # increment degree of v by 1
    self.degree[w] += 1      # increment degree of w by 1
 
 
# Method to return roots which gives minimum height to tree
def rootForMinimumHeight(self):
 
    from queue import Queue
    q = Queue()
 
    # First enqueue all leaf nodes in queue
    for i in range(self.V):
        if self.degree[i] == 1:
            q.put(i)
 
    # loop until total vertex remains less than 2
    while(self.V > 2):
        p = q.qsize()
        self.V -= p
        for i in range(p):
            t = q.get()
 
            # for each neighbour, decrease its degree and
            # if it become leaf, insert into queue
            for j in self.adj[t]:
                self.degree[j] -= 1
                if self.degree[j] == 1:
                    q.put(j)
 
    #  Copying the result from queue to result vector
    res = list()
    while(q.qsize() > 0):
        res.append(q.get())
 
    return res
 
 
# Driver code
g = Graph(6, addEdge, rootForMinimumHeight)
g.addEdge(0, 3)
g.addEdge(1, 3)
g.addEdge(2, 3)
g.addEdge(4, 3)
g.addEdge(5, 4)
 
# Function call
res = g.rootForMinimumHeight()
for i in res:
    print (i,end=" ")
 
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)


C#




// C# program to find root which gives minimum height to
// tree
 
using System;
using System.Collections.Generic;
 
// This class represents a undirected graph using adjacency
// list representation
class Graph {
    private int V; // No. of vertices
 
    // Pointer to an array containing adjacency lists
    private List<int>[] adj;
 
    // List which stores degree of all vertices
    private List<int> degree;
 
    public Graph(int v) // Constructor
    {
        V = v;
        adj = new List<int>[ v ];
        degree = new List<int>();
        for (int i = 0; i < v; i++) {
            adj[i] = new List<int>();
            degree.Add(0);
        }
    }
 
    public void AddEdge(int v, int w) // To add an edge
    {
        adj[v].Add(w); // Add w to v’s list
        adj[w].Add(v); // Add v to w’s list
        degree[v]++; // increment degree of v by 1
        degree[w]++; // increment degree of w by 1
    }
 
    // function to get roots which give minimum height
    public List<int> RootForMinimumHeight()
    {
        Queue<int> q = new Queue<int>();
 
        // first enqueue all leaf nodes in queue
        for (int i = 0; i < V; i++) {
            if (degree[i] == 1)
                q.Enqueue(i);
        }
 
        // loop until total vertex remains less than 2
        while (V > 2) {
            int popEle = q.Count;
            V -= popEle; // popEle number of vertices will
                         // be popped
 
            for (int i = 0; i < popEle; i++) {
                int t = q.Dequeue();
 
                // for each neighbour, decrease its degree
                // and if it become leaf, insert into queue
                foreach(int j in adj[t])
                {
                    degree[j]--;
                    if (degree[j] == 1)
                        q.Enqueue(j);
                }
            }
        }
 
        // copying the result from queue to result List
        List<int> res = new List<int>();
        while (q.Count > 0) {
            res.Add(q.Dequeue());
        }
        return res;
    }
}
 
class GFG {
    // Driver code
    static void Main(string[] args)
    {
        Graph g = new Graph(6);
        g.AddEdge(0, 3);
        g.AddEdge(1, 3);
        g.AddEdge(2, 3);
        g.AddEdge(4, 3);
        g.AddEdge(5, 4);
 
        // Function Call
        List<int> res = g.RootForMinimumHeight();
        foreach(int i in res) Console.Write(i + " ");
        Console.WriteLine();
    }
}
 
// This code is contributed by cavi4762.


Javascript




// JavaScript program to find root which gives minimum height to tree
class Graph {
    constructor(V) {
        this.V = V;
        this.adj = new Array(V).fill(null).map(() => []);
        this.degree = new Array(V).fill(0);
    }
 
    // Method to add an edge
    addEdge(v, w) {
        this.adj[v].push(w);
        this.adj[w].push(v);
        this.degree[v]++;
        this.degree[w]++;
    }
 
    // Method to return roots which gives minimum height to tree
    rootForMinimumHeight() {
        const q = []; // first enqueue all leaf nodes in queue
        for (let i = 0; i < this.V; i++) {
            if (this.degree[i] === 1) {
                q.push(i);
            }
        }
 
        // loop until total vertex remains less than 2
        while (this.V > 2) {
            const popEle = q.length;
            this.V -= popEle; // popEle number of vertices will be popped
 
            for (let i = 0; i < popEle; i++) {
                const t = q.shift();
 
                // for each neighbour, decrease its degree and
                // if it become leaf, insert into queue
                for (let j = 0; j < this.adj[t].length; j++) {
                    const neighbour = this.adj[t][j];
                    this.degree[neighbour]--;
                    if (this.degree[neighbour] === 1) {
                        q.push(neighbour);
                    }
                }
            }
        }
 
        // copying the result from queue to result array
        const res = [];
        while (q.length > 0) {
            res.push(q.shift());
        }
        return res;
    }
}
 
// Driver code
const g = new Graph(6);
g.addEdge(0, 3);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(4, 3);
g.addEdge(5, 4);
 
// Function Call
const res = g.rootForMinimumHeight();
console.log(res.join(" "));


Output

3 4 

Time Complexity :O(N), here N is the number of nodes in the tree because we consider each node only once.

Auxiliary Space : O(N+ K), here  N is the number of nodes in the graph and K denotes the number of edges.

As we are accessing each node once, the total time complexity of the solution is O(n).



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