查找节点 X 是否存在于另一个节点 Y 的子树中,反之亦然,用于 Q 查询
给定一棵具有N个节点和(N-1) 条边的树,源节点位于第 1 个位置。有Q个查询,每个查询的类型都是{pos, X, Y} 。根据查询的类型执行以下操作:
- 如果pos = 0 ,则查找Y是否存在于X的子树中。
- 如果pos = 1 ,则查找X是否存在于Y的子树中。
例子:
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.
方法:问题的解决方案是基于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)