给定一个 N 元树,其中N个顶点以1 为根,并且 一组顶点作为V[] ,任务是打印任何这样的顶点U使得从根到U的路径由距离V[]最远距离1的所有顶点组成。如果没有获得顶点,则打印“No” 。否则,打印U的值。
例子:
Input: N = 10, Edges[][] = {{1, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {3, 7}, {7, 8}, {7, 9}, {9, 10}}, V[] = {4, 3, 8, 9, 10}
Output: 10
Explanation: Path from root to node 10 contain {1, 3, 7, 9, 10} and 8 is at distance 1 from this path.
Input: N = 10, Edges[][] = {{1, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {3, 7}, {7, 8}, {7, 9}, {9, 10}}, V[] = {3, 4, 2, 8}
Output: 8
Explanation: Path from root to node 8 contain {1, 3, 7, 8}. Now, 4 and 2 are at distance 1 from this path.
朴素的方法:朴素的想法是找到从根 1 到每个节点的所有可能路径,并在从根到所选顶点的路径中选择包含给定集合V[] 的所有所需顶点或具有距离的那个1 从那条路。
时间复杂度: O(N!)
辅助空间: O(N 2 )
高效的方法:可以通过预先计算每个顶点到根的距离来优化上述方法。这种预先计算有助于发现某个顶点P是否是给定树中某个其他顶点C的父节点。以下是步骤:
- 从根节点 1 执行 DFS Traversal 并存储给定树中每个节点的访问前和访问后时间。
- 现在,顶点V是顶点U的父当且仅当V的前时间小于或等于U的前时间和后时间的U是大于或等于V的交时间。
- 可以注意到,从根顶点到给定集合V[] 中最深顶点的路径是所需的结果。
- 现在,问题减少到检查,如果每个顶点的给定集合V []母公司是集合V最深的顶点的祖先[]。
- 因此,将每个顶点替换为其父节点(根除外),并通过上述属性检查每个父节点是否是最深顶点的祖先。
- 如果条件满足则打印最深的顶点,否则打印“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