📌  相关文章
📜  检查给定节点是否在节点U和V之间的路径中

📅  最后修改于: 2021-04-22 09:19:35             🧑  作者: Mango

给定二叉树的三个顶点UVR ,任务是检查R是否位于UV之间的路径中。如果路径中不存在,则打印“否”,否则打印“是”
例子:

方法:想法是使用两个节点的最低公共祖先。在UV之间的路径中存在R的以下情况:

  1. RUV的最低共同祖先。

  1. R是在UV的最低共同祖先的左子树,是高于V。

  1. RUV的最低共同祖先的右子树中,并且在U之上。

要了解有关最低的祖先的更多信息,请在此处阅读该帖子。
下面是上述方法的实现:

C++
// CPP Program to implement the above appraoch
#include 
using namespace std;
 
class GfG
{
  public:
 
  // Table for storing 2^ith parent
  vector> table;
 
  // Variable to store the height of the tree
  int height;
 
  // Graph
  vector> Graph;
 
  // Arrays to mark start and end time for a node
  vector timeIn, timeOut;
 
  // Timer
  int time;
 
  // constructor for initializing
  // the global variables
  GfG(int n)
  {
 
    // log(n) with base 2
    height = (int)ceil(log2(n));
 
    // Filling with -1 as initial
    table.resize(n + 1, vector(height + 1, -1));
 
    // Fill the graph with empty lists
    Graph.resize(n + 1);
    timeIn.resize(n + 1);
    timeOut.resize(n + 1);
    time = 0;
  }
 
  // Dfs for pre-processing sparse table and
  // calculating start and end time
  void dfs(int s, int p)
  {
 
    // Parent at 1 node distance is always
    // it's direct parent
    table[s][0] = p;
 
    // Start time noted
    timeIn[s] = ++time;
 
    // Filling sparse table recursively
    for (int i = 1; i <= height; i++)
      table[s][i] = table[table[s][i - 1]][i - 1];
 
    // Traversing children of source
    for (int child : Graph[s]) {
      if (child == p) continue;
      dfs(child, s);
    }
 
    // End time noted
    timeOut[s] = ++time;
  }
 
  // Helper function to check lowest common Ancestor
  bool check(int u, int v)
  {
    return timeIn[u] <= timeIn[v] && timeOut[u] >= timeOut[v];
  }
 
  // Function to return Lowest Common Ancestor of U and V
  int lowestCommonAncestor(int U, int V)
  {
    if (check(U, V)) return U;
 
    if (check(V, U)) return V;
 
    for (int i = height; i >= 0; i--)
    {
      if (!check(table[U][i], V)) U = table[U][i];
    }
 
    return table[U][0];
  }
 
  // Function that return true if R
  // exists on the path between U
  // and V in the given tree
  bool isPresent(int U, int V, int R)
  {
 
    // Dfs
    dfs(1, 1);
 
    // Calculating LCA between U and V
    int LCA = lowestCommonAncestor(U, V);
 
    // Calculating LCA between U and R
    int LCA_1 = lowestCommonAncestor(U, R);
 
    // Calculating LCA between U and V
    int LCA_2 = lowestCommonAncestor(V, R);
 
    if (LCA == R || (LCA_1 == LCA && LCA_2 == R) ||
        (LCA_2 == LCA && LCA_1 == R)) {
      return true;
    }
    return false;
  }
};
 
// Driver code
int main(int argc, char const *argv[])
{
 
  // Number of vertices
  int n = 6;
  GfG *obj = new GfG(n);
 
  // Create the graph
  obj->Graph[1].push_back(2);
  obj->Graph[2].push_back(1);
  obj->Graph[1].push_back(3);
  obj->Graph[3].push_back(1);
  obj->Graph[2].push_back(4);
  obj->Graph[4].push_back(2);
  obj->Graph[2].push_back(5);
  obj->Graph[5].push_back(2);
  obj->Graph[3].push_back(6);
  obj->Graph[6].push_back(3);
 
  int U = 4, V = 6, R = 2;
  if (obj->isPresent(U, V, R))
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
}
 
// This code is contributed by sanjeev2552


Java
// Java implementation of the approach
import java.util.*;
 
class GfG {
 
    // Table for storing 2^ith parent
    private static int table[][];
 
    // Variable to store the height of the tree
    private static int height;
 
    // Graph
    private static ArrayList > Graph;
 
    // Arrays to mark start and end time for a node
    private static int timeIn[];
    private static int timeOut[];
 
    // Timer
    private static int time;
 
    // Private constructor for initializing
    // the global variables
    private GfG(int n)
    {
 
        // log(n) with base 2
        height = (int)Math.ceil(Math.log10(n) / Math.log10(2));
        table = new int[n + 1][height + 1];
 
        // Fill the graph with empty lists
        Graph = new ArrayList >();
        for (int i = 0; i <= n; i++)
            Graph.add(new ArrayList());
        timeIn = new int[n + 1];
        timeOut = new int[n + 1];
        time = 0;
    }
 
    // Filling with -1 as initial
    private static void preprocessing(int n)
    {
        for (int i = 0; i < n + 1; i++) {
            Arrays.fill(table[i], -1);
        }
    }
 
    // Dfs for pre-processing sparse table and
    // calculating start and end time
    private static void dfs(int s, int p)
    {
        // Parent at 1 node distance is always
        // it's direct parent
        table[s][0] = p;
 
        // Start time noted
        timeIn[s] = ++time;
 
        // Filling sparse table recursively
        for (int i = 1; i <= height; i++)
            table[s][i] = table[table[s][i - 1]][i - 1];
 
        // Traversing children of source
        for (int child : Graph.get(s)) {
            if (child == p)
                continue;
            dfs(child, s);
        }
 
        // End time noted
        timeOut[s] = ++time;
    }
 
    // Helper function to check lowest common Ancestor
    private static boolean check(int u, int v)
    {
        return timeIn[u] <= timeIn[v] && timeOut[u] >= timeOut[v];
    }
 
    // Function to return Lowest Common Ancestor of U and V
    private static int lowestCommonAncestor(int U, int V)
    {
        if (check(U, V))
            return U;
 
        if (check(V, U))
            return V;
 
        for (int i = height; i >= 0; i--) {
            if (!check(table[U][i], V))
                U = table[U][i];
        }
 
        return table[U][0];
    }
 
    // Function that return true if R
    // exists on the path between U
    // and V in the given tree
    private static boolean isPresent(int U, int V, int R)
    {
 
        // Dfs
        dfs(1, 1);
 
        // Calculating LCA between U and V
        int LCA = lowestCommonAncestor(U, V);
 
        // Calculating LCA between U and R
        int LCA_1 = lowestCommonAncestor(U, R);
 
        // Calculating LCA between U and V
        int LCA_2 = lowestCommonAncestor(V, R);
 
        if (LCA == R || (LCA_1 == LCA && LCA_2 == R)
            || (LCA_2 == LCA && LCA_1 == R)) {
            return true;
        }
        return false;
    }
 
    // Driver code
    public static void main(String args[])
    {
        // Number of vertices
        int n = 6;
        GfG obj = new GfG(n);
 
        // Create the graph
        preprocessing(n);
        Graph.get(1).add(2);
        Graph.get(2).add(1);
        Graph.get(1).add(3);
        Graph.get(3).add(1);
        Graph.get(2).add(4);
        Graph.get(4).add(2);
        Graph.get(2).add(5);
        Graph.get(5).add(2);
        Graph.get(3).add(6);
        Graph.get(6).add(3);
 
        int U = 4, V = 6, R = 2;
        if (isPresent(U, V, R))
            System.out.print("Yes");
        else
            System.out.print("No");
    }
}


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GfG
{
 
    // Table for storing 2^ith parent
    private static int [,]table;
 
    // Variable to store the height of the tree
    private static int height;
 
    // Graph
    private static List > Graph;
 
    // Arrays to mark start and end time for a node
    private static int []timeIn;
    private static int []timeOut;
 
    // Timer
    private static int time;
 
    // Private constructor for initializing
    // the global variables
    private GfG(int n)
    {
 
        // log(n) with base 2
        height = (int)Math.Ceiling(Math.Log10(n) / Math.Log10(2));
        table = new int[n + 1, height + 1];
 
        // Fill the graph with empty lists
        Graph = new List >();
        for (int i = 0; i <= n; i++)
            Graph.Add(new List());
        timeIn = new int[n + 1];
        timeOut = new int[n + 1];
        time = 0;
    }
 
    // Filling with -1 as initial
    private static void preprocessing(int n)
    {
        for (int i = 0; i < n + 1; i++)
        {
            for(int j = 0; j < height + 1; j++)
                table[i, j] = -1;
        }
    }
 
    // Dfs for pre-processing sparse table and
    // calculating start and end time
    private static void dfs(int s, int p)
    {
        // Parent at 1 node distance is always
        // it's direct parent
        table[s, 0] = p;
 
        // Start time noted
        timeIn[s] = ++time;
 
        // Filling sparse table recursively
        for (int i = 1; i <= height; i++)
            table[s, i] = table[table[s, i - 1], i - 1];
 
        // Traversing children of source
        foreach (int child in Graph[s])
        {
            if (child == p)
                continue;
            dfs(child, s);
        }
 
        // End time noted
        timeOut[s] = ++time;
    }
 
    // Helper function to check lowest common Ancestor
    private static bool check(int u, int v)
    {
        return timeIn[u] <= timeIn[v] && timeOut[u] >= timeOut[v];
    }
 
    // Function to return Lowest Common Ancestor of U and V
    private static int lowestCommonAncestor(int U, int V)
    {
        if (check(U, V))
            return U;
 
        if (check(V, U))
            return V;
 
        for (int i = height; i >= 0; i--)
        {
            if (!check(table[U, i], V))
                U = table[U, i];
        }
 
        return table[U, 0];
    }
 
    // Function that return true if R
    // exists on the path between U
    // and V in the given tree
    private static bool isPresent(int U, int V, int R)
    {
 
        // Dfs
        dfs(1, 1);
 
        // Calculating LCA between U and V
        int LCA = lowestCommonAncestor(U, V);
 
        // Calculating LCA between U and R
        int LCA_1 = lowestCommonAncestor(U, R);
 
        // Calculating LCA between U and V
        int LCA_2 = lowestCommonAncestor(V, R);
 
        if (LCA == R || (LCA_1 == LCA && LCA_2 == R)
            || (LCA_2 == LCA && LCA_1 == R))
        {
            return true;
        }
        return false;
    }
 
    // Driver code
    public static void Main(String []args)
    {
        // Number of vertices
        int n = 6;
        GfG obj = new GfG(n);
 
        // Create the graph
        preprocessing(n);
        Graph[1].Add(2);
        Graph[2].Add(1);
        Graph[1].Add(3);
        Graph[3].Add(1);
        Graph[2].Add(4);
        Graph[4].Add(2);
        Graph[2].Add(5);
        Graph[5].Add(2);
        Graph[3].Add(6);
        Graph[6].Add(3);
 
        int U = 4, V = 6, R = 2;
        if (isPresent(U, V, R))
            Console.Write("Yes");
        else
            Console.Write("No");
    }
}
 
// This code is contributed by PrinciRaj1992


输出:
Yes

时间复杂度: O(NlogN)用于预处理,logN用于查找最低的共同祖先。