Roots of a tree which give minimum height
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++
#include <bits/stdc++.h>
using namespace std;
class Graph
{
public :
int V;
list< int > *adj;
vector< int > degree;
Graph( int V);
void addEdge( int v, int w);
vector< int > rootForMinimumHeight();
};
Graph::Graph( int V)
{
this ->V = V;
adj = new list< int >[V];
for ( int i = 0; i < V; i++)
degree.push_back(0);
}
void Graph::addEdge( int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v);
degree[v]++;
degree[w]++;
}
vector< int > Graph::rootForMinimumHeight()
{
queue< int > q;
for ( int i = 0; i < V; i++)
if (degree[i] == 1)
q.push(i);
while (V > 2)
{
int popEle = q.size();
V -= popEle;
for ( int i = 0; i < popEle; i++)
{
int t = q.front();
q.pop();
for ( auto j = adj[t].begin(); j != adj[t].end(); j++)
{
degree[*j]--;
if (degree[*j] == 1)
q.push(*j);
}
}
}
vector< int > res;
while (!q.empty())
{
res.push_back(q.front());
q.pop();
}
return res;
}
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);
vector< int > res = g.rootForMinimumHeight();
for ( int i = 0; i < res.size(); i++)
cout << res[i] << " " ;
cout << endl;
}
|
Java
import java.io.*;
import java.util.*;
class Graph {
private int V;
private LinkedList<Integer>[] adj;
private int [] degree;
@SuppressWarnings ( "unchecked" )
public Graph( int v)
{
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)
{
adj[v].add(w);
adj[w].add(v);
degree[v]++;
degree[w]++;
}
public LinkedList<Integer> rootForMinimumHeight()
{
Queue<Integer> q = new LinkedList<>();
for ( int i = 0 ; i < V; i++) {
if (degree[i] == 1 )
q.add(i);
}
while (V > 2 ) {
int popEle = q.size();
V -= popEle;
for ( int i = 0 ; i < popEle; i++) {
int t = q.poll();
for ( int j : adj[t]) {
degree[j]--;
if (degree[j] == 1 )
q.add(j);
}
}
}
LinkedList<Integer> res = new LinkedList<Integer>();
while (!q.isEmpty()) {
res.add(q.poll());
}
return res;
}
}
public class GFG {
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 );
LinkedList<Integer> res = g.rootForMinimumHeight();
for ( int i : res)
System.out.print(i + " " );
System.out.println();
}
}
|
Python3
class Graph:
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 )
Graph.addEdge = addEdge
Graph.rootForMinimumHeight = rootForMinimumHeight
def addEdge( self , v, w):
self .adj[v].append(w)
self .adj[w].append(v)
self .degree[v] + = 1
self .degree[w] + = 1
def rootForMinimumHeight( self ):
from queue import Queue
q = Queue()
for i in range ( self .V):
if self .degree[i] = = 1 :
q.put(i)
while ( self .V > 2 ):
p = q.qsize()
self .V - = p
for i in range (p):
t = q.get()
for j in self .adj[t]:
self .degree[j] - = 1
if self .degree[j] = = 1 :
q.put(j)
res = list ()
while (q.qsize() > 0 ):
res.append(q.get())
return res
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 )
res = g.rootForMinimumHeight()
for i in res:
print (i,end = " " )
|
C#
using System;
using System.Collections.Generic;
class Graph {
private int V;
private List< int >[] adj;
private List< int > degree;
public Graph( int v)
{
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)
{
adj[v].Add(w);
adj[w].Add(v);
degree[v]++;
degree[w]++;
}
public List< int > RootForMinimumHeight()
{
Queue< int > q = new Queue< int >();
for ( int i = 0; i < V; i++) {
if (degree[i] == 1)
q.Enqueue(i);
}
while (V > 2) {
int popEle = q.Count;
V -= popEle;
for ( int i = 0; i < popEle; i++) {
int t = q.Dequeue();
foreach ( int j in adj[t])
{
degree[j]--;
if (degree[j] == 1)
q.Enqueue(j);
}
}
}
List< int > res = new List< int >();
while (q.Count > 0) {
res.Add(q.Dequeue());
}
return res;
}
}
class GFG {
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);
List< int > res = g.RootForMinimumHeight();
foreach ( int i in res) Console.Write(i + " " );
Console.WriteLine();
}
}
|
Javascript
class Graph {
constructor(V) {
this .V = V;
this .adj = new Array(V).fill( null ).map(() => []);
this .degree = new Array(V).fill(0);
}
addEdge(v, w) {
this .adj[v].push(w);
this .adj[w].push(v);
this .degree[v]++;
this .degree[w]++;
}
rootForMinimumHeight() {
const q = [];
for (let i = 0; i < this .V; i++) {
if ( this .degree[i] === 1) {
q.push(i);
}
}
while ( this .V > 2) {
const popEle = q.length;
this .V -= popEle;
for (let i = 0; i < popEle; i++) {
const t = q.shift();
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);
}
}
}
}
const res = [];
while (q.length > 0) {
res.push(q.shift());
}
return res;
}
}
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);
const res = g.rootForMinimumHeight();
console.log(res.join( " " ));
|
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
Share your thoughts in the comments
Please Login to comment...