用于 Q 查询的子树中距 S 距离 K 处的节点数
给定一棵由N个节点组成并以节点1为根的树,还给定一个由M对组成的数组Q[] ,其中每个数组元素表示一个(S, K)形式的查询。任务是为数组的每个查询(S, K)打印节点S的子树中距离K处的节点数。
例子:
Input: Q[] = {{2, 1}, {1, 1}},
Output: 3
2
Explanation:
- Query(2, 1): Print 3, as there are 3 nodes 4, 5, and 6 at the distance of 1 in the subtree of node 2.
- Query(1, 1): Print 2, as there are 2 nodes 2, and 3 at the distance of 1 in the subtree of node 1.
Input: Edges = {{1, 2}, {2, 3}, {3, 4}}, Q[] = {{1, 2}, {2, 2}}
Output: 1 1
朴素方法:最简单的方法是让每个查询从节点S运行深度优先搜索(DFS),并找到与给定节点S距离为K的所有节点。
时间复杂度: O(N*Q)
辅助空间: O(1)
有效方法:上述方法可以根据以下观察进行优化:
- Suppose, tin[] stores the entry time of every node and tout[] stores the exit time of a node according to dfs traversal of the tree.
- Then, for two nodes, A and B, B will be in the subtree of A if and only if:
- tin[B]≥tin[A] and tout[B]≤tout[A]
- Suppose, levels[], where levels[i] store the entry times of all nodes present at depth i.
- Then, using binary search nodes at a distance K from a node can be found.
请按照以下步骤解决问题:
- 初始化三个数组,比如tin[] 、 tout[]和depth[]来分别存储节点的进入时间、退出时间和深度。
- 初始化两个 2D 向量,比如adj和levels ,以存储每个节点在特定深度的邻接列表和进入时间。
- 初始化一个变量,比如t为1,以跟踪时间。
- 定义一个递归 DFS函数,比如dfs(node, parent, d) ,并执行以下步骤:
- 将t分配给tin[node] ,然后将t加1。
- 将tin[node]推入向量levels[d]中,然后将d分配给depth[node]。
- 遍历节点的子节点,并将递归函数调用为每个子节点 X 的dfs(X, node, d+1) 。
- 完成上述步骤后,将t赋值给tout[node]并将t加1。
- 调用递归函数dfs(1, 1, 0)。
- 使用变量i遍历数组Q[]并执行以下操作:
- 将当前数组元素的值存储为S = Q [i].first 和K = Q[i].second。
- 在向量levels[depth[S]+K]中找到所有大于tin[S]的节点的计数,并将其存储在变量L中。
- 在向量级别[depth[S]+K]中找到所有大于tout[S]的节点的计数,并将其存储在变量R中。
- 打印RL的值作为当前查询的答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
int tin[100], tout[100], depth[100];
int t = 0;
// Function to add edges
void Add_edge(int parent, int child,
vector >& adj)
{
adj[parent].push_back(child);
adj[child].push_back(parent);
}
// Function to perform Depth First Search
void dfs(int node, int parent, vector >& adj,
vector >& levels, int d)
{
// Stores the entry time of a node
tin[node] = t++;
// Stores the entering time
// of a node at depth d
levels[d].push_back(tin[node]);
depth[node] = d;
// Iterate over the children of node
for (auto x : adj[node]) {
if (x != parent)
dfs(x, node, adj, levels, d + 1);
}
// Stores the Exit time of a node
tout[node] = t++;
}
// Function to find number of nodes
// at distance K from node S in the
// subtree of S
void numberOfNodes(int node, int dist,
vector >& levels)
{
// Distance from root node
dist += depth[node];
// Index of node with greater tin value
// then tin[S]
int start = lower_bound(levels[dist].begin(),
levels[dist].end(), tin[node])
- levels[dist].begin();
// Index of node with greater tout value then tout[S]
int ed = lower_bound(levels[dist].begin(),
levels[dist].end(), tout[node])
- levels[dist].begin();
// Answer to the Query
cout << ed - start << endl;
}
// Function for performing DFS
// and answer to queries
void numberOfNodesUtil(pair Q[], int M, int N)
{
vector > adj(N + 5), levels(N + 5);
Add_edge(1, 2, adj);
Add_edge(1, 3, adj);
Add_edge(2, 4, adj);
Add_edge(2, 5, adj);
Add_edge(2, 6, adj);
t = 1;
// DFS function call
dfs(1, 1, adj, levels, 0);
// Traverse the array Q[]
for (int i = 0; i < M; ++i) {
numberOfNodes(Q[i].first, Q[i].second, levels);
}
}
// Driver Code
int main()
{
// Input
int N = 6;
pair Q[] = { { 2, 1 }, { 1, 1 } };
int M = sizeof(Q) / sizeof(Q[0]);
// Function call
numberOfNodesUtil(Q, M, N);
}
Python3
# Python3 program for the above approach
from bisect import bisect_left, bisect_right
tin = [0] * 100
tout = [0] * 100
depth = [0] * 100
t = 0
# Function to add edges
def Add_edge(parent, child, adj):
adj[parent].append(child)
adj[child].append(parent)
return adj
# Function to perform Depth First Search
def dfs(node, parent, d):
global tin, tout, depth, adj, levels, t
# Stores the entry time of a node
tin[node] = t
t += 1
# Stores the entering time
# of a node at depth d
levels[d].append(tin[node])
depth[node] = d
# Iterate over the children of node
for x in adj[node]:
if (x != parent):
dfs(x, node, d + 1)
# Stores the Exit time of a node
tout[node] = t
t += 1
# Function to find number of nodes
# at distance K from node S in the
# subtree of S
def numberOfNodes(node, dist):
global levels, tin, tout
# Distance from root node
dist += depth[node]
# Index of node with greater tin value
# then tin[S]
start = bisect_left(levels[dist], tin[node])
# Index of node with greater tout value then tout[S]
ed = bisect_left(levels[dist], tout[node])
# Answer to the Query
print(ed - start)
# Function for performing DFS
# and answer to queries
def numberOfNodesUtil(Q, M, N):
global t, adj
adj = Add_edge(1, 2, adj)
adj = Add_edge(1, 3, adj)
adj = Add_edge(2, 4, adj)
adj = Add_edge(2, 5, adj)
adj = Add_edge(2, 6, adj)
t = 1
# DFS function call
dfs(1, 1, 0)
# Traverse the array Q[]
for i in range(M):
numberOfNodes(Q[i][0], Q[i][1])
# Driver Code
if __name__ == '__main__':
# Input
N = 6
Q = [ [ 2, 1 ], [ 1, 1 ] ]
M = len(Q)
adj = [[] for i in range(N+5)]
levels = [[] for i in range(N + 5)]
# Function call
numberOfNodesUtil(Q, M, N)
# This code is contributed by mohit kumar 29
输出
3
2
时间复杂度: O(N + M*log(N))
辅助空间: O(N)