📌  相关文章
📜  查找节点 X 是否存在于另一个节点 Y 的子树中,反之亦然,用于 Q 查询

📅  最后修改于: 2022-05-13 01:56:05.538000             🧑  作者: Mango

查找节点 X 是否存在于另一个节点 Y 的子树中,反之亦然,用于 Q 查询

给定一棵具有N个节点和(N-1) 条边的树,源节点位于第 1 个位置。有Q个查询,每个查询的类型都是{pos, X, Y} 。根据查询的类型执行以下操作:

  • 如果pos = 0 ,则查找Y是否存在于X的子树中。
  • 如果pos = 1 ,则查找X是否存在于Y的子树中。

例子:

方法:问题的解决方案是基于DFS 。为每个节点占用时间和退出时间。使用它可以很容易地检查任何节点是否存在于其他节点的子树中。请按照以下步骤操作:

  • 首先,使用树的DFS 遍历找到每个节点(最初我们的计时器为 1)的时间(我们进入该节点的时间)和退出时间(我们离开该节点的时间)。
  • 然后对于每个查询,根据其类型查找Y 是否存在于 X 的子树中,反之亦然。
  • 要检查Y是否存在于X的子树中,请检查Y 的时间是否大于 X并且Y 的时间是否小于 X ,而检查X是否存在于Y的子树中正好相反。

下面是上述方法的实现。

C++
// C++ program to implement the approach
#include 
using namespace std;
 
// Initial timer=1
int timer = 1;
 
// Simple DFS Function
void dfs(vector 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 >& edges,
           int Q, vector >& query)
{
    vector 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 > edges
        = { { 1, 2 }, { 1, 3 }, { 2, 6 },
            { 2, 7 }, { 6, 9 }, { 7, 8 },
            { 3, 4 }, { 3, 5 } };
    int Q = 5;
    vector > 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 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 []adj = new Vector[N + 1];
    for (int i = 0; i < adj.length; i++)
      adj[i] = new Vector();
 
    // 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 []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 []adj = new List[N + 1];
    for (int i = 0; i < adj.Length; i++)
      adj[i] = new List();
 
    // 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



输出
Yes
No
No
No
Yes

时间复杂度: O(max (N, Q))
辅助空间: O(N)