Find node U containing all nodes from a set V at atmost distance 1 from the path from root to U

Given a N-ary tree with N vertices rooted at 1 and a set of vertices as V[], the task is to print any such vertex U such that the path from the root to U consists of all the vertices from V[] at utmost distance 1. If no vertex is obtained, then print “No”. Else, print the value of U.

Examples:

Input: N = 10, Edges[][] = {{1, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {3, 7}, {7, 8}, {7, 9}, {9, 10}}, V[] = {4, 3, 8, 9, 10}

Output: 10
Explanation: Path from root to node 10 contain {1, 3, 7, 9, 10} and 8 is at distance 1 from this path. 



Input: N = 10, Edges[][] = {{1, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {3, 7}, {7, 8}, {7, 9}, {9, 10}}, V[] = {3, 4, 2, 8}

Output: 8
Explanation: Path from root to node 8 contain {1, 3, 7, 8}. Now, 4 and 2 are at distance 1 from this path.

Naive Approach: The naive idea is to find all possible path from the root 1 to every node and choose the one which contains all the required vertices of the given set V[] in the path from the root to that chosen vertex or has a distance 1 from that path. 
Time Complexity: O(N!) 
Auxiliary Space: O(N2)

Efficient Approach: The above approach can be optimized by precomputing the distances of every vertex from root. This pre-computing helps in finding if some vertex P is a parent of some other vertex C in the given tree or not. Below are the steps:

  1. Perform DFS Traversal from the root node 1 and store the pre and post visited time of each node in the given tree.
  2. Now, vertex V is the parent of the vertex U if and only if the pre-time of V is smaller than or equal to the pre-time of U and post time of U is greater than or equal to post time of V.
  3. It can be noted that the path of the deepest vertex in the given set V[] from the root vertex is the required result.
  4. Now, the problem reduced to check if every vertex’s parent in the given set V[] is the ancestor of the deepest vertex in set V[].
  5. Therefore, replace each vertex with its parent(except the root) and check that each parent is the ancestor of the deepest vertex by above mention property.
  6. If the condition satisfies then print the deepest vertex, otherwise print “No”.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// To store the time
int timeT = 0;
 
// Function to perform DFS
// to store times, distance
// and parent of each node
void dfs(int u, int p, int dis,
         vector<int>& vis,
         vector<int>& distance,
         vector<int>& parent,
         vector<int>& preTime,
         vector<int>& postTime,
         vector<int> Adj[])
{
    // Update the distance of node u
    distance[u] = dis;
 
    // Update parent of node u
    parent[u] = p;
    vis[u] = 1;
 
    // Increment time timeT
    timeT++;
 
    // Discovery time of node u
    preTime[u] = timeT;
 
    // Traverse the adjacency list
    // of current node and recursively
    // call DFS for each vertex
    for (int i = 0; i < Adj[u].size(); i++) {
 
        // If current node Adj[u][i]
        // is unvisted
        if (vis[Adj[u][i]] == 0) {
 
            dfs(Adj[u][i], u, dis + 1,
                vis, distance, parent,
                preTime, postTime, Adj);
        }
    }
 
    timeT++;
 
    // Update the finishing time
    postTime[u] = timeT;
}
 
// Function to add edges between
// nodes u and v
void addEdge(vector<int> Adj[],
             int u, int v)
{
    Adj[u].push_back(v);
    Adj[v].push_back(u);
}
 
// Function to find the node U
// such that path from root to U
// contains nodes in V[]
void findNodeU(int N, int V,
               int Vertices[],
               int Edges[][2])
{
 
    // Initialise vis, dis, parent,
    // preTime, and postTime
    vector<int> vis(N + 1, 0);
    vector<int> distance(N + 1, 0);
    vector<int> parent(N + 1, 0);
    vector<int> preTime(N + 1, 0);
    vector<int> postTime(N + 1, 0);
 
    // Store Adjacency List
    vector<int> Adj[N + 1];
 
    int u, v;
 
    // Create adjacency List
    for (int i = 0; i < N - 1; i++) {
        addEdge(Adj, Edges[i][0],
                Edges[i][1]);
    }
 
    // Perform DFS Traversal
    dfs(1, 0, 0, vis, distance, parent,
        preTime, postTime, Adj);
 
    int maximumDistance = 0;
 
    // Stores the distance
    // of deepest vertex 'u'
    maximumDistance = 0;
 
    // Update the deepest node by
    // traversing the qu[]
    for (int k = 0; k < V; k++) {
 
        // Find deepest vertex
        if (maximumDistance
            < distance[Vertices[k]]) {
 
            maximumDistance
                = distance[Vertices[k]];
            u = Vertices[k];
        }
 
        // Replace each vertex with it's
        // corresponding parent except
        // the root vertex
        if (parent[Vertices[k]] != 0) {
            Vertices[k]
                = parent[Vertices[k]];
        }
    }
 
    bool ans = true;
 
    bool flag;
 
    for (int k = 0; k < V; k++) {
 
        // Checks if the ancestor
        // with respect to deepest
        // vertex u
        if (preTime[Vertices[k]]
                <= preTime[u]
            && postTime[Vertices[k]]
                   >= postTime[u])
            flag = true;
        else
            flag = false;
 
        // Update ans
        ans = ans & flag;
    }
 
    // Print the result
    if (ans)
        cout << u;
    else
        cout << "NO";
}
 
// Driver Code
int main()
{
    // Total vertices
    int N = 10;
 
    int V = 5;
 
    // Given set of vertices
    int Vertices[] = { 4, 3, 8, 9, 10 };
 
    // Given edges
    int Edges[][2] = { { 1, 2 }, { 1, 3 },
                       { 1, 4 }, { 2, 5 },
                       { 2, 6 }, { 3, 7 },
                       { 7, 8 }, { 7, 9 }, 
                       { 9, 10 } };
 
    // Function Call
    findNodeU(N, V, Vertices, Edges);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach
import java.util.*;
 
class GFG{
     
// To store the time
static int timeT = 0;
 
// Function to perform DFS
// to store times, distance
// and parent of each node
static void dfs(int u, int p, int dis, int vis[],
                int distance[], int parent[],
                int preTime[], int postTime[],
                ArrayList<ArrayList<Integer>> Adj)
{
     
    // Update the distance of node u
    distance[u] = dis;
 
    // Update parent of node u
    parent[u] = p;
    vis[u] = 1;
 
    // Increment time timeT
    timeT++;
 
    // Discovery time of node u
    preTime[u] = timeT;
 
    // Traverse the adjacency list
    // of current node and recursively
    // call DFS for each vertex
    for(int i = 0; i < Adj.get(u).size(); i++)
    {
 
        // If current node Adj[u][i]
        // is unvisted
        if (vis[Adj.get(u).get(i)] == 0)
        {
            dfs(Adj.get(u).get(i), u, dis + 1,
                vis, distance, parent, preTime,
                postTime, Adj);
        }
    }
 
    timeT++;
 
    // Update the finishing time
    postTime[u] = timeT;
}
 
// Function to add edges between
// nodes u and v
static void addEdge(ArrayList<ArrayList<Integer>> Adj,
                    int u, int v)
{
    Adj.get(u).add(v);
    Adj.get(v).add(u);
}
 
// Function to find the node U
// such that path from root to U
// contains nodes in V[]
static void findNodeU(int N, int V,
                      int Vertices[],
                      int Edges[][])
{
 
    // Initialise vis, dis, parent,
    // preTime, and postTime
    int vis[] = new int[N + 1];
    int distance[] = new int[N + 1];
    int parent[] = new int[N + 1];
    int preTime[] = new int[N + 1];
    int postTime[] = new int[N + 1];
 
    // Store Adjacency List
    ArrayList<
    ArrayList<Integer>> Adj = new ArrayList<>();
    for(int i = 0; i < N + 1; i++)
        Adj.add(new ArrayList<Integer>());
         
    int u = 0, v;
 
    // Create adjacency List
    for(int i = 0; i < N - 1; i++)
    {
        addEdge(Adj, Edges[i][0], Edges[i][1]);
    }
 
    // Perform DFS Traversal
    dfs(1, 0, 0, vis, distance,
        parent, preTime, postTime, Adj);
 
    int maximumDistance = 0;
 
    // Stores the distance
    // of deepest vertex 'u'
    maximumDistance = 0;
 
    // Update the deepest node by
    // traversing the qu[]
    for(int k = 0; k < V; k++)
    {
 
        // Find deepest vertex
        if (maximumDistance <
            distance[Vertices[k]])
        {
            maximumDistance =
            distance[Vertices[k]];
            u = Vertices[k];
        }
 
        // Replace each vertex with it's
        // corresponding parent except
        // the root vertex
        if (parent[Vertices[k]] != 0)
        {
            Vertices[k] = parent[Vertices[k]];
        }
    }
 
    boolean ans = true;
    boolean flag;
 
    for(int k = 0; k < V; k++)
    {
 
        // Checks if the ancestor
        // with respect to deepest
        // vertex u
        if (preTime[Vertices[k]] <= preTime[u] &&
           postTime[Vertices[k]] >= postTime[u])
            flag = true;
        else
            flag = false;
 
        // Update ans
        ans = ans & flag;
    }
 
    // Print the result
    if (ans)
        System.out.println(u);
    else
        System.out.println("NO");
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Total vertices
    int N = 10;
 
    int V = 5;
 
    // Given set of vertices
    int Vertices[] = { 4, 3, 8, 9, 10 };
 
    // Given edges
    int Edges[][] = { { 1, 2 }, { 1, 3 },
                      { 1, 4 }, { 2, 5 },
                      { 2, 6 }, { 3, 7 },
                      { 7, 8 }, { 7, 9 },
                      { 9, 10 } };
 
    // Function call
    findNodeU(N, V, Vertices, Edges);
}
}
 
// This code is contributed by jrishabh99

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for
// the above approach
using System;
using System.Collections.Generic;
class GFG{
     
// To store the time
static int timeT = 0;
 
// Function to perform DFS
// to store times, distance
// and parent of each node
static void dfs(int u, int p, int dis, int []vis,
                int []distance, int []parent,
                int []preTime, int []postTime,
                List<List<int>> Adj)
{
  // Update the distance of node u
  distance[u] = dis;
 
  // Update parent of node u
  parent[u] = p;
  vis[u] = 1;
 
  // Increment time timeT
  timeT++;
 
  // Discovery time of node u
  preTime[u] = timeT;
 
  // Traverse the adjacency list
  // of current node and recursively
  // call DFS for each vertex
  for(int i = 0; i < Adj[u].Count; i++)
  {
    // If current node Adj[u,i]
    // is unvisted
    if (vis[Adj[u][i]] == 0)
    {
      dfs(Adj[u][i], u, dis + 1,
          vis, distance, parent, preTime,
          postTime, Adj);
    }
  }
 
  timeT++;
 
  // Update the finishing time
  postTime[u] = timeT;
}
 
// Function to add edges between
// nodes u and v
static void addEdge(List<List<int>> Adj,
                    int u, int v)
{
  Adj[u].Add(v);
  Adj[v].Add(u);
}
 
// Function to find the node U
// such that path from root to U
// contains nodes in V[]
static void findNodeU(int N, int V,
                      int []Vertices,
                      int [,]Edges)
{
  // Initialise vis, dis, parent,
  // preTime, and postTime
  int []vis = new int[N + 1];
  int []distance = new int[N + 1];
  int []parent = new int[N + 1];
  int []preTime = new int[N + 1];
  int []postTime = new int[N + 1];
 
  // Store Adjacency List
  List<List<int>> Adj = new List<List<int>>();
  for(int i = 0; i < N + 1; i++)
    Adj.Add(new List<int>());
 
  int u = 0, v;
 
  // Create adjacency List
  for(int i = 0; i < N - 1; i++)
  {
    addEdge(Adj, Edges[i, 0], Edges[i, 1]);
  }
 
  // Perform DFS Traversal
  dfs(1, 0, 0, vis, distance,
      parent, preTime, postTime, Adj);
 
  int maximumDistance = 0;
 
  // Stores the distance
  // of deepest vertex 'u'
  maximumDistance = 0;
 
  // Update the deepest node by
  // traversing the qu[]
  for(int k = 0; k < V; k++)
  {
    // Find deepest vertex
    if (maximumDistance <
        distance[Vertices[k]])
    {
      maximumDistance = distance[Vertices[k]];
      u = Vertices[k];
    }
 
    // Replace each vertex with it's
    // corresponding parent except
    // the root vertex
    if (parent[Vertices[k]] != 0)
    {
      Vertices[k] = parent[Vertices[k]];
    }
  }
 
  bool ans = true;
  bool flag;
 
  for(int k = 0; k < V; k++)
  {
    // Checks if the ancestor
    // with respect to deepest
    // vertex u
    if (preTime[Vertices[k]] <= preTime[u] &&
        postTime[Vertices[k]] >= postTime[u])
      flag = true;
    else
      flag = false;
 
    // Update ans
    ans = ans & flag;
  }
 
  // Print the result
  if (ans)
    Console.WriteLine(u);
  else
    Console.WriteLine("NO");
}
 
// Driver Code
public static void Main(String[] args)
{    
  // Total vertices
  int N = 10;
 
  int V = 5;
 
  // Given set of vertices
  int []Vertices = {4, 3, 8, 9, 10};
 
  // Given edges
  int [,]Edges = {{1, 2}, {1, 3},
                  {1, 4}, {2, 5},
                  {2, 6}, {3, 7},
                  {7, 8}, {7, 9},
                  {9, 10}};
 
  // Function call
  findNodeU(N, V, Vertices, Edges);
}
}
 
// This code is contributed by gauravrajput1

chevron_right


Output: 

10


 

Time Complexity: O(N + V), where N is the total vertices and V is the size of the given set.
Auxiliary Space: O(5*N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : jrishabh99, GauravRajput1