📌  相关文章
📜  从根到 U 的路径最远距离 1 处,找到包含集合 V 中所有节点的节点 U

📅  最后修改于: 2021-09-06 11:08:32             🧑  作者: Mango

给定一个 N 元树,其中N个顶点以1 为根,并且 一组顶点作为V[] ,任务是打印任何这样的顶点U使得从根到U的路径由距离V[]最远距离1的所有顶点组成。如果没有获得顶点,则打印“No” 。否则,打印U的值。

例子:

朴素的方法:朴素的想法是找到从根 1 到每个节点的所有可能路径,并在从根到所选顶点的路径中选择包含给定集合V[] 的所有所需顶点或具有距离的那个1 从那条路。
时间复杂度: O(N!)
辅助空间: O(N 2 )

高效的方法:可以通过预先计算每个顶点到根的距离来优化上述方法。这种预先计算有助于发现某个顶点P是否是给定树中某个其他顶点C的父节点。以下是步骤:

  1. 从根节点 1 执行 DFS Traversal 并存储给定树中每个节点的访问前和访问后时间。
  2. 现在,顶点V是顶点U的父当且仅当V的前时间小于或等于U的前时间和后时间的U是大于或等于V的交时间。
  3. 可以注意到,从根顶点到给定集合V[] 中最深顶点的路径是所需的结果。
  4. 现在,问题减少到检查,如果每个顶点的给定集合V []母公司是集合V最深的顶点的祖先[]。
  5. 因此,将每个顶点替换为其父节点(除外),并通过上述属性检查每个父节点是否是最深顶点的祖先。
  6. 如果条件满足则打印最深的顶点,否则打印“No”

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
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& vis,
         vector& distance,
         vector& parent,
         vector& preTime,
         vector& postTime,
         vector 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 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 vis(N + 1, 0);
    vector distance(N + 1, 0);
    vector parent(N + 1, 0);
    vector preTime(N + 1, 0);
    vector postTime(N + 1, 0);
 
    // Store Adjacency List
    vector 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;
}


Java
// 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> 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> 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> Adj = new ArrayList<>();
    for(int i = 0; i < N + 1; i++)
        Adj.add(new ArrayList());
         
    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


Python3
# Python3 program for the above approach
  
# To store the time
timeT = 0;
  
# Function to perform DFS
# to store times, distance
# and parent of each node
def dfs(u, p, dis,
          vis,
          distance,
          parent,
          preTime,
          postTime,
          Adj):
     
    global timeT
     
    # Update the distance of node u
    distance[u] = dis;
  
    # Update parent of node u
    parent[u] = p;
    vis[u] = 1;
  
    # Increment time timeT
    timeT += 1
  
    # Discovery time of node u
    preTime[u] = timeT;
  
    # Traverse the adjacency list
    # of current node and recursively
    # call DFS for each vertex
    for i in range(len(Adj[u])):
  
        # 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 += 1
  
    # Update the finishing time
    postTime[u] = timeT;
 
# Function to add edges between
# nodes u and v
def addEdge(Adj,u, v):
 
    Adj[u].append(v);
    Adj[v].append(u);
  
# Function to find the node U
# such that path from root to U
# contains nodes in V[]
def findNodeU(N, V, Vertices, Edges):
  
    # Initialise vis, dis, parent,
    # preTime, and postTime
    vis = [0 for i in range(N + 1)]
    distance = [0 for i in range(N + 1)]
    parent = [0 for i in range(N + 1)]
    preTime = [0 for i in range(N + 1)]
    postTime = [0 for i in range(N + 1)]
  
    # Store Adjacency List
    Adj = [[] for i in range(N + 1)]
  
    u = 0
    v = 0
  
    # Create adjacency List
    for i in range(N - 1):
     
        addEdge(Adj, Edges[i][0],
                Edges[i][1]);
  
    # Perform DFS Traversal
    dfs(1, 0, 0, vis, distance, parent,
        preTime, postTime, Adj);
  
    maximumDistance = 0;
  
    # Stores the distance
    # of deepest vertex 'u'
    maximumDistance = 0;
  
    # Update the deepest node by
    # traversing the qu[]
    for k in range(V):
  
        # 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]];
          
    ans = True;
  
    flag = False
     
    for k in range(V):
  
        # Checks if the ancestor
        # with respect to deepest
        # vertex u
        if (preTime[Vertices[k]] <= preTime[u]
                and postTime[Vertices[k]]
                   >= postTime[u]):
            flag = True;
        else:
            flag = False;
  
        # Update ans
        ans = ans & flag;
      
    # Prthe result
    if (ans):
        print(u)
    else:
        print('No')
  
# Driver Code
if __name__=='__main__':
     
    # Total vertices
    N = 10;
  
    V = 5;
  
    # Given set of vertices
    Vertices = [ 4, 3, 8, 9, 10 ];
  
    # Given edges
    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 rutvik_56


C#
// 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> 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> 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> Adj = new List>();
  for(int i = 0; i < N + 1; i++)
    Adj.Add(new List());
 
  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


输出:
10

时间复杂度: O(N + V),其中 N 是总顶点数,V 是给定集合的大小。
辅助空间: O(5*N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live