Skip to content
Related Articles

Related Articles

Finding if a node X is present in subtree of another node Y or vice versa for Q queries

Improve Article
Save Article
  • Difficulty Level : Expert
  • Last Updated : 29 Mar, 2022
Improve Article
Save Article

Given a tree with N nodes and (N-1) edges and source node is at 1st position. There are Q queries, each of the type {pos, X, Y}. Perform the following operation based on the type of the  query:

  • If pos = 0, then find if Y is present in the subtree of X.
  • If pos = 1, then find if X is present in the subtree of Y.

Examples:

Input: N: = 9, edges = {{1, 2}, {1, 3}, {2, 6}, {2, 7}, {6, 9}, {7, 8}, {3, 4}, {3, 5}}
Q = 5, query = {{0, 2, 8}, {1, 2, 8}, {1, 6, 5}, {0, 6, 5}, {1, 9, 1}}
Output: {Yes, No, No, No, Yes}
Explanation: See the image below. 
8 is present in the subtree of 2 and 9 is also present in the subtree of 9.
For the other queries it does not satisfy the condition.

Input: N = 2, edges = {{1, 2}}
Q = 1, query = {0, 2, 1}
Output: {No}
Explanation: 1 is not present in the subtree of 2.

 

Approach: The solution of the problem is based on the DFS. Take in time and out time for each node. Using this it can be easily checked if any node is present in the subtree of other node or not. Follow the steps mentioned below:

  • At first, find in time( time at which we are entering at that node) and out time (time at which we are leaving that node ) for each of the nodes (initially our timer is 1) using DFS traversal of the tree.
  • Then for each of the queries, according to its type find if Y is present in the subtree of X or vice-versa.
  • To check if Y is present in the subtree of X check if in time of Y is more than X and out time of Y is less than X and just the opposite to check if X is present in the subtree of Y.

Below is the implementation of the above approach.

C++




// C++ program to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Initial timer=1
int timer = 1;
 
// Simple DFS Function
void dfs(vector<int> adj[], int itime[],
         int otime[], int src, int par)
{
    // While visiting a node
    // mark its timer in time and
    // increase timer for next nodes
    itime[src] = timer++;
    for (auto it : adj[src]) {
        if (it != par) {
            dfs(adj, itime, otime, it, src);
        }
    }
 
    // While leaving a node
    // mark its timer in out time
    // and increase timer for next nodes
    otime[src] = timer++;
}
 
// Check for subtree
bool check(int itime[], int otime[],
           int x, int y)
{
    // Intime of y should be more
    // and outime should be less than x
    if (itime[x] < itime[y]
        && otime[x] > otime[y])
        return true;
    return false;
}
 
// Function to solve the queries
void solve(int N, vector<vector<int> >& edges,
           int Q, vector<vector<int> >& query)
{
    vector<int> adj[N + 1];
 
    // N-1 edges given
    for (int i = 0; i < N - 1; i++) {
        adj[edges[i][0]].push_back(edges[i][1]);
        adj[edges[i][1]].push_back(edges[i][0]);
    }
 
    // Array for intime
    int intime[N + 1];
 
    // Array for outime
    int outtime[N + 1];
 
    // Using DFS function
    // to find intime and outtime
    dfs(adj, intime, outtime, 1, -1);
 
    for (int i = 0; i < Q; i++) {
        int type = query[i][0],
            X = query[i][1],
            Y = query[i][2];
        if (type == 0) {
            if (check(intime, outtime, X, Y)) {
 
                // To check if Y is present
                // in subtree of X
                cout << "Yes" << endl;
            }
            else {
                cout << "No" << endl;
            }
        }
        else {
            if (check(intime, outtime, Y, X)) {
 
                // To check if X is present
                // in subtree of Y
                cout << "Yes" << endl;
            }
            else {
                cout << "No" << endl;
            }
        }
    }
}
 
// Driver code
int main()
{
    int N = 9;
 
    // N is the number of nodes
    vector<vector<int> > edges
        = { { 1, 2 }, { 1, 3 }, { 2, 6 },
            { 2, 7 }, { 6, 9 }, { 7, 8 },
            { 3, 4 }, { 3, 5 } };
    int Q = 5;
    vector<vector<int> > query = { { 0, 2, 8 },
                                   { 1, 2, 8 },
                                   { 1, 6, 5 },
                                   { 0, 6, 5 },
                                   { 1, 9, 1 } };
    solve(N, edges, Q, query);
    return 0;
}


Java




// Java program to implement the approach
import java.util.*;
 
class GFG{
 
  // Initial timer=1
  static int timer = 1;
 
  // Simple DFS Function
  static void dfs(Vector<Integer> adj[], int itime[],
                  int otime[], int src, int par)
  {
 
    // While visiting a node
    // mark its timer in time and
    // increase timer for next nodes
    itime[src] = timer++;
    for (int it : adj[src]) {
      if (it != par) {
        dfs(adj, itime, otime, it, src);
      }
    }
 
    // While leaving a node
    // mark its timer in out time
    // and increase timer for next nodes
    otime[src] = timer++;
  }
 
  // Check for subtree
  static boolean check(int itime[], int otime[],
                       int x, int y)
  {
    // Intime of y should be more
    // and outime should be less than x
    if (itime[x] < itime[y]
        && otime[x] > otime[y])
      return true;
    return false;
  }
 
  // Function to solve the queries
  static void solve(int N, int[][] edges,
                    int Q, int[][] query)
  {
    Vector<Integer> []adj = new Vector[N + 1];
    for (int i = 0; i < adj.length; i++)
      adj[i] = new Vector<Integer>();
 
    // N-1 edges given
    for (int i = 0; i < N - 1; i++) {
      adj[edges[i][0]].add(edges[i][1]);
      adj[edges[i][1]].add(edges[i][0]);
    }
 
    // Array for intime
    int []intime = new int[N + 1];
 
    // Array for outime
    int []outtime = new int[N + 1];
 
    // Using DFS function
    // to find intime and outtime
    dfs(adj, intime, outtime, 1, -1);
 
    for (int i = 0; i < Q; i++) {
      int type = query[i][0],
      X = query[i][1],
      Y = query[i][2];
      if (type == 0) {
        if (check(intime, outtime, X, Y)) {
 
          // To check if Y is present
          // in subtree of X
          System.out.print("Yes" +"\n");
        }
        else {
          System.out.print("No" +"\n");
        }
      }
      else {
        if (check(intime, outtime, Y, X)) {
 
          // To check if X is present
          // in subtree of Y
          System.out.print("Yes" +"\n");
        }
        else {
          System.out.print("No" +"\n");
        }
      }
    }
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 9;
 
    // N is the number of nodes
    int[][] edges
      = { { 1, 2 }, { 1, 3 }, { 2, 6 },
         { 2, 7 }, { 6, 9 }, { 7, 8 },
         { 3, 4 }, { 3, 5 } };
    int Q = 5;
    int[][] query = { { 0, 2, 8 },
                     { 1, 2, 8 },
                     { 1, 6, 5 },
                     { 0, 6, 5 },
                     { 1, 9, 1 } };
    solve(N, edges, Q, query);
  }
}
 
// This code is contributed by 29AjayKumar


C#




// C# program to implement the approach
using System;
using System.Collections.Generic;
 
public class GFG{
 
  // Initial timer=1
  static int timer = 1;
 
  // Simple DFS Function
  static void dfs(List<int> []adj, int []itime,
                  int []otime, int src, int par)
  {
 
    // While visiting a node
    // mark its timer in time and
    // increase timer for next nodes
    itime[src] = timer++;
    foreach (int it in adj[src]) {
      if (it != par) {
        dfs(adj, itime, otime, it, src);
      }
    }
 
    // While leaving a node
    // mark its timer in out time
    // and increase timer for next nodes
    otime[src] = timer++;
  }
 
  // Check for subtree
  static bool check(int []itime, int []otime,
                    int x, int y)
  {
    // Intime of y should be more
    // and outime should be less than x
    if (itime[x] < itime[y]
        && otime[x] > otime[y])
      return true;
    return false;
  }
 
  // Function to solve the queries
  static void solve(int N, int[,] edges,
                    int Q, int[,] query)
  {
    List<int> []adj = new List<int>[N + 1];
    for (int i = 0; i < adj.Length; i++)
      adj[i] = new List<int>();
 
    // N-1 edges given
    for (int i = 0; i < N - 1; i++) {
      adj[edges[i,0]].Add(edges[i,1]);
      adj[edges[i,1]].Add(edges[i,0]);
    }
 
    // Array for intime
    int []intime = new int[N + 1];
 
    // Array for outime
    int []outtime = new int[N + 1];
 
    // Using DFS function
    // to find intime and outtime
    dfs(adj, intime, outtime, 1, -1);
 
    for (int i = 0; i < Q; i++) {
      int type = query[i,0],
      X = query[i,1],
      Y = query[i,2];
      if (type == 0) {
        if (check(intime, outtime, X, Y)) {
 
          // To check if Y is present
          // in subtree of X
          Console.Write("Yes" +"\n");
        }
        else {
          Console.Write("No" +"\n");
        }
      }
      else {
        if (check(intime, outtime, Y, X)) {
 
          // To check if X is present
          // in subtree of Y
          Console.Write("Yes" +"\n");
        }
        else {
          Console.Write("No" +"\n");
        }
      }
    }
  }
 
  // Driver code
  public static void Main(String[] args)
  {
    int N = 9;
 
    // N is the number of nodes
    int[,] edges
      = { { 1, 2 }, { 1, 3 }, { 2, 6 },
         { 2, 7 }, { 6, 9 }, { 7, 8 },
         { 3, 4 }, { 3, 5 } };
    int Q = 5;
    int[,] query = { { 0, 2, 8 },
                    { 1, 2, 8 },
                    { 1, 6, 5 },
                    { 0, 6, 5 },
                    { 1, 9, 1 } };
    solve(N, edges, Q, query);
  }
}
 
// This code is contributed by Rajput-Ji


 
 

Output

Yes
No
No
No
Yes

 

Time Complexity: O(max (N, Q))
Auxiliary Space: O(N)

 


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!