Open In App

Find the node at the center of an N-ary tree

Last Updated : 02 Dec, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisites: 

Given a N-ary tree with N nodes numbered from 0 to N-1 and a list of undirected edges, the task is to find the node(s) at the center of the given tree.

Eccentricity: The eccentricity of any vertex V in a given tree is the maximum distance between the given vertex V and any other vertex of the tree. 
Center: The center of a tree is the vertex having the minimum eccentricity. Hence, it means that in order to find the center we have to minimize this eccentricity. 
 

Examples:  

Input: N = 4, Edges[] = { (1, 0), (1, 2), (1, 3)} 
Output:
Explanation: 

Input: N = 6, Edges[] = { (0, 3), (1, 3), (2, 3), (4, 3), (5, 4)} 
Output: 3, 4 
Explanation: 

Approach: It can be observed that the path of maximum eccentricity is the diameter of the tree. Hence, the center of the tree diameter will be the center of the tree as well.

Proof: 

  • For example, Let’s consider a case where the longest path consists of odd number of vertices. Let the longest path be X —— O ——– Y where X and Y are the two endpoints of the path and O is the middle vertex.
  • For a contradiction, if the center of the tree is not O but some other vertex O’, then at least one of the following two statements must be true. 
    1. Path XO’ is strictly longer than path XO
    2. Path YO’ is strictly longer than path YO
  • This means O’ will not satisfy the condition of minimum eccentricity. Hence by contradiction, we have proved that the center of the tree is actually the center of the diameter path.
  • Now if the diameter consists odd number of nodes, then there exists only 1 center (also known as Central Tree).
  • If diameter consists of even number of nodes, then there are 2 center nodes(also known as Bi-central Tree). 
     

Below is the implementation of the above approach:  

C++




// C++ implementation of
// the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// To create tree
map<int, vector<int> > tree;
 
// Function to store the path
// from given vertex to the target
// vertex in a vector path
bool getDiameterPath(int vertex,
                     int targetVertex,
                     int parent,
                     vector<int>& path)
{
 
    // If the target node is found,
    // push it into path vector
    if (vertex == targetVertex) {
 
        path.push_back(vertex);
        return true;
    }
 
    for (auto i : tree[vertex]) {
 
        // To prevent visiting a
        // node already visited
        if (i == parent)
            continue;
 
        // Recursive call to the neighbours
        // of current node inorder
        // to get the path
        if (getDiameterPath(i, targetVertex,
                            vertex, path)) {
            path.push_back(vertex);
            return true;
        }
    }
 
    return false;
}
 
// Function to obtain and return the
// farthest node from a given vertex
void farthestNode(int vertex, int parent,
                  int height, int& maxHeight,
                  int& maxHeightNode)
{
 
    // If the current height is maximum
    // so far, then save the current node
    if (height > maxHeight) {
        maxHeight = height;
        maxHeightNode = vertex;
    }
 
    // Iterate over all the neighbours
    // of current node
    for (auto i : tree[vertex]) {
        // This is to prevent visiting
        // a already visited node
        if (i == parent)
            continue;
 
        // Next call will be at 1 height
        // higher than our current height
        farthestNode(i, vertex,
                     height + 1,
                     maxHeight,
                     maxHeightNode);
    }
}
 
// Function to add edges
void addedge(int a, int b)
{
    tree[a].push_back(b);
    tree[b].push_back(a);
}
 
void FindCenter(int n)
{
    // Now we will find the 1st farthest
    // node from 0(any arbitrary node)
 
    // Perform DFS from 0 and update
    // the maxHeightNode to obtain
    // the farthest node from 0
 
    // Reset to -1
    int maxHeight = -1;
 
    // Reset to -1
    int maxHeightNode = -1;
 
    farthestNode(0, -1, 0, maxHeight,
                 maxHeightNode);
 
    // Stores one end of the diameter
    int leaf1 = maxHeightNode;
 
    // Similarly the other end of
    // the diameter
 
    // Reset the maxHeight
    maxHeight = -1;
    farthestNode(maxHeightNode,
                 -1, 0, maxHeight,
                 maxHeightNode);
 
    // Stores the second end
    // of the diameter
    int leaf2 = maxHeightNode;
 
    // Store the diameter into
    // the vector path
    vector<int> path;
 
    // Diameter is equal to the
    // path between the two farthest
    // nodes leaf1 and leaf2
    getDiameterPath(leaf1, leaf2,
                    -1, path);
 
    int pathSize = path.size();
 
    if (pathSize % 2) {
        cout << path[pathSize / 2]
             << endl;
    }
    else {
        cout << path[pathSize / 2]
             << ", "
             << path[(pathSize - 1) / 2]
             << endl;
    }
}
 
// Driver Code
int main()
{
 
    int N = 4;
    addedge(1, 0);
    addedge(1, 2);
    addedge(1, 3);
 
    FindCenter(N);
 
    return 0;
}


Java




// Java implementation of
// the above approach
import java.util.*;
 
class GFG{
 
// To create tree
static Map<Integer, ArrayList<Integer>> tree;
static ArrayList<Integer> path;
static int maxHeight, maxHeightNode;
 
// Function to store the path
// from given vertex to the target
// vertex in a vector path
static boolean getDiameterPath(int vertex,
                               int targetVertex,
                               int parent,
                               ArrayList<Integer> path)
{
 
    // If the target node is found,
    // push it into path vector
    if (vertex == targetVertex)
    {
        path.add(vertex);
        return true;
    }
 
    for(Integer i : tree.get(vertex))
    {
         
        // To prevent visiting a
        // node already visited
        if (i == parent)
            continue;
 
        // Recursive call to the neighbours
        // of current node inorder
        // to get the path
        if (getDiameterPath(i, targetVertex,
                            vertex, path))
        {
            path.add(vertex);
            return true;
        }
    }
    return false;
}
 
// Function to obtain and return the
// farthest node from a given vertex
static void farthestNode(int vertex, int parent,
                         int height)
{
     
    // If the current height is maximum
    // so far, then save the current node
    if (height > maxHeight)
    {
        maxHeight = height;
        maxHeightNode = vertex;
    }
 
    // Iterate over all the neighbours
    // of current node
    if (tree.get(vertex) != null)
        for(Integer i : tree.get(vertex))
        {
             
            // This is to prevent visiting
            // a already visited node
            if (i == parent)
                continue;
 
            // Next call will be at 1 height
            // higher than our current height
            farthestNode(i, vertex,
                         height + 1);
        }
}
 
// Function to add edges
static void addedge(int a, int b)
{
    if (tree.get(a) == null)
        tree.put(a, new ArrayList<>());
 
    tree.get(a).add(b);
 
    if (tree.get(b) == null)
        tree.put(b, new ArrayList<>());
 
    tree.get(b).add(a);
}
 
static void FindCenter(int n)
{
     
    // Now we will find the 1st farthest
    // node from 0(any arbitrary node)
 
    // Perform DFS from 0 and update
    // the maxHeightNode to obtain
    // the farthest node from 0
 
    // Reset to -1
    maxHeight = -1;
 
    // Reset to -1
    maxHeightNode = -1;
 
    farthestNode(0, -1, 0);
 
    // Stores one end of the diameter
    int leaf1 = maxHeightNode;
 
    // Similarly the other end of
    // the diameter
 
    // Reset the maxHeight
    maxHeight = -1;
    farthestNode(maxHeightNode,
                 -1, 0);
 
    // Stores the second end
    // of the diameter
    int leaf2 = maxHeightNode;
 
    // Store the diameter into
    // the vector path
    path = new ArrayList<>();
 
    // Diameter is equal to the
    // path between the two farthest
    // nodes leaf1 and leaf2
    getDiameterPath(leaf1, leaf2,
                    -1, path);
 
    int pathSize = path.size();
 
    if (pathSize % 2 == 1)
    {
        System.out.println(path.get(pathSize / 2));
    }
    else {
        System.out.println(path.get(pathSize / 2) +
                    ", " + path.get((pathSize - 1) / 2));
    }
}
 
// Driver code
public static void main(String[] args)
{
    int N = 4;
 
    tree = new HashMap<>();
    addedge(1, 0);
    addedge(1, 2);
    addedge(1, 3);
 
    FindCenter(N);
}
}
 
// This code is contributed by offbeat


Python3




# Python3 implementation of the above approach
 
# To create tree
tree = {}
path = []
maxHeight, maxHeightNode = -1, -1
 
# Function to store the path
# from given vertex to the target
# vertex in a vector path
def getDiameterPath(vertex, targetVertex, parent, path):
   
    # If the target node is found,
    # push it into path vector
    if (vertex == targetVertex):
        path.append(vertex)
        return True
 
    for i in range(len(tree[vertex])):
        # To prevent visiting a
        # node already visited
        if (tree[vertex][i] == parent):
            continue
 
        # Recursive call to the neighbours
        # of current node inorder
        # to get the path
        if (getDiameterPath(tree[vertex][i], targetVertex, vertex, path)):
            path.append(vertex)
            return True
    return False
 
# Function to obtain and return the
# farthest node from a given vertex
def farthestNode(vertex, parent, height):
    global maxHeight, maxHeightNode
    # If the current height is maximum
    # so far, then save the current node
    if (height > maxHeight):
        maxHeight = height
        maxHeightNode = vertex
 
    # Iterate over all the neighbours
    # of current node
    if (vertex in tree):
        for i in range(len(tree[vertex])):
           
            # This is to prevent visiting
            # a already visited node
            if (tree[vertex][i] == parent):
                continue
                 
            # Next call will be at 1 height
            # higher than our current height
            farthestNode(tree[vertex][i], vertex, height + 1)
 
# Function to add edges
def addedge(a, b):
    if (a not in tree):
        tree[a] = []
 
    tree[a].append(b)
 
    if (b not in tree):
        tree[b] = []
 
    tree[b].append(a)
 
def FindCenter(n):
    # Now we will find the 1st farthest
    # node from 0(any arbitrary node)
 
    # Perform DFS from 0 and update
    # the maxHeightNode to obtain
    # the farthest node from 0
 
    # Reset to -1
    maxHeight = -1
 
    # Reset to -1
    maxHeightNode = -1
 
    farthestNode(0, -1, 0)
 
    # Stores one end of the diameter
    leaf1 = maxHeightNode
 
    # Similarly the other end of
    # the diameter
 
    # Reset the maxHeight
    maxHeight = -1
    farthestNode(maxHeightNode, -1, 0)
 
    # Stores the second end
    # of the diameter
    leaf2 = maxHeightNode
 
    # Store the diameter into
    # the vector path
    path = []
 
    # Diameter is equal to the
    # path between the two farthest
    # nodes leaf1 and leaf2
    getDiameterPath(leaf1, leaf2, -1, path)
 
    pathSize = len(path)
 
    if (pathSize % 2 == 1):
        print(path[int(pathSize / 2)]*-1)
    else:
        print(path[int(pathSize / 2)], ", ", path[int((pathSize - 1) / 2)], sep = "", end = "")
 
N = 4
   
tree = {}
addedge(1, 0)
addedge(1, 2)
addedge(1, 3)
 
FindCenter(N)
 
# This code is contributed by suresh07.


C#




// C# implementation of
// the above approach
using System;
using System.Collections.Generic;
class GFG {
     
    // To create tree
    static Dictionary<int, List<int>> tree;
    static List<int> path;
    static int maxHeight, maxHeightNode;
      
    // Function to store the path
    // from given vertex to the target
    // vertex in a vector path
    static bool getDiameterPath(int vertex,
                                   int targetVertex,
                                   int parent,
                                   List<int> path)
    {
      
        // If the target node is found,
        // push it into path vector
        if (vertex == targetVertex)
        {
            path.Add(vertex);
            return true;
        }
      
        foreach(int i in tree[vertex])
        {
              
            // To prevent visiting a
            // node already visited
            if (i == parent)
                continue;
      
            // Recursive call to the neighbours
            // of current node inorder
            // to get the path
            if (getDiameterPath(i, targetVertex,
                                vertex, path))
            {
                path.Add(vertex);
                return true;
            }
        }
        return false;
    }
      
    // Function to obtain and return the
    // farthest node from a given vertex
    static void farthestNode(int vertex, int parent,
                             int height)
    {
          
        // If the current height is maximum
        // so far, then save the current node
        if (height > maxHeight)
        {
            maxHeight = height;
            maxHeightNode = vertex;
        }
      
        // Iterate over all the neighbours
        // of current node
        if (tree.ContainsKey(vertex) && tree[vertex].Count > 0)
        {
            foreach(int i in tree[vertex])
            {
                  
                // This is to prevent visiting
                // a already visited node
                if (i == parent)
                    continue;
      
                // Next call will be at 1 height
                // higher than our current height
                farthestNode(i, vertex, height + 1);
            }
        }
    }
      
    // Function to add edges
    static void addedge(int a, int b)
    {
        if (!tree.ContainsKey(a))
            tree[a] = new List<int>();
      
        tree[a].Add(b);
      
        if (!tree.ContainsKey(b))
            tree[b] = new List<int>();
      
        tree[b].Add(a);
    }
      
    static void FindCenter(int n)
    {
          
        // Now we will find the 1st farthest
        // node from 0(any arbitrary node)
      
        // Perform DFS from 0 and update
        // the maxHeightNode to obtain
        // the farthest node from 0
      
        // Reset to -1
        maxHeight = -1;
      
        // Reset to -1
        maxHeightNode = -1;
      
        farthestNode(0, -1, 0);
      
        // Stores one end of the diameter
        int leaf1 = maxHeightNode;
      
        // Similarly the other end of
        // the diameter
      
        // Reset the maxHeight
        maxHeight = -1;
        farthestNode(maxHeightNode,
                     -1, 0);
      
        // Stores the second end
        // of the diameter
        int leaf2 = maxHeightNode;
      
        // Store the diameter into
        // the vector path
        path = new List<int>();
      
        // Diameter is equal to the
        // path between the two farthest
        // nodes leaf1 and leaf2
        getDiameterPath(leaf1, leaf2,
                        -1, path);
      
        int pathSize = path.Count;
      
        if (pathSize % 2 == 1)
        {
            Console.WriteLine(path[pathSize / 2]);
        }
        else {
            Console.WriteLine(path[pathSize / 2] +
                        ", " + path[(pathSize - 1) / 2]);
        }
    }
 
  static void Main() {
    int N = 4;
  
    tree = new Dictionary<int, List<int>>();
    addedge(1, 0);
    addedge(1, 2);
    addedge(1, 3);
  
    FindCenter(N);
  }
}
 
// This code is contributed by divyesh072019.


Javascript




<script>
    // Javascript implementation of the above approach
     
    // To create tree
    let tree;
    let path;
    let maxHeight, maxHeightNode;
 
    // Function to store the path
    // from given vertex to the target
    // vertex in a vector path
    function getDiameterPath(vertex, targetVertex, parent, path)
    {
 
        // If the target node is found,
        // push it into path vector
        if (vertex == targetVertex)
        {
            path.push(vertex);
            return true;
        }
 
        for(let i = 0; i < tree.get(vertex).length; i++)
        {
 
            // To prevent visiting a
            // node already visited
            if (tree.get(vertex)[i] == parent)
                continue;
 
            // Recursive call to the neighbours
            // of current node inorder
            // to get the path
            if (getDiameterPath(tree.get(vertex)[i], targetVertex,
                                vertex, path))
            {
                path.push(vertex);
                return true;
            }
        }
        return false;
    }
 
    // Function to obtain and return the
    // farthest node from a given vertex
    function farthestNode(vertex, parent, height)
    {
 
        // If the current height is maximum
        // so far, then save the current node
        if (height > maxHeight)
        {
            maxHeight = height;
            maxHeightNode = vertex;
        }
 
        // Iterate over all the neighbours
        // of current node
        if (tree.get(vertex) != null)
            for(let i = 0; i < tree.get(vertex).length; i++)
            {
 
                // This is to prevent visiting
                // a already visited node
                if (tree.get(vertex)[i] == parent)
                    continue;
 
                // Next call will be at 1 height
                // higher than our current height
                farthestNode(tree.get(vertex)[i], vertex, height + 1);
            }
    }
 
    // Function to add edges
    function addedge(a, b)
    {
        if (tree.get(a) == null)
            tree.set(a, []);
 
        tree.get(a).push(b);
 
        if (tree.get(b) == null)
            tree.set(b, []);
 
        tree.get(b).push(a);
    }
 
    function FindCenter(n)
    {
 
        // Now we will find the 1st farthest
        // node from 0(any arbitrary node)
 
        // Perform DFS from 0 and update
        // the maxHeightNode to obtain
        // the farthest node from 0
 
        // Reset to -1
        maxHeight = -1;
 
        // Reset to -1
        maxHeightNode = -1;
 
        farthestNode(0, -1, 0);
 
        // Stores one end of the diameter
        let leaf1 = maxHeightNode;
 
        // Similarly the other end of
        // the diameter
 
        // Reset the maxHeight
        maxHeight = -1;
        farthestNode(maxHeightNode,
                     -1, 0);
 
        // Stores the second end
        // of the diameter
        let leaf2 = maxHeightNode;
 
        // Store the diameter into
        // the vector path
        path = [];
 
        // Diameter is equal to the
        // path between the two farthest
        // nodes leaf1 and leaf2
        getDiameterPath(leaf1, leaf2,
                        -1, path);
 
        let pathSize = path.length;
 
        if (pathSize % 2 == 1)
        {
            document.write(path[parseInt(pathSize / 2, 10)]);
        }
        else {
            document.write(path[parseInt(pathSize / 2, 10)] +
                        ", " + path[parseInt((pathSize - 1) / 2, 10)]);
        }
    }
     
    let N = 4;
  
    tree = new Map();
    addedge(1, 0);
    addedge(1, 2);
    addedge(1, 3);
  
    FindCenter(N);
 
 
</script>


Output: 

1

 

Time Complexity: O(N) 
Auxiliary Space: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads