📜  门|门 IT 2008 |第 34 题(1)

📅  最后修改于: 2023-12-03 14:58:36.408000             🧑  作者: Mango

门|门 IT 2008 |第34题

题目要求:给定一棵n个节点的有根树和Q个询问,每次查询一个节点在树上的深度以及它的第k个祖先,其中1<=k<=d(节点深度),d为根节点的深度(即树的高度)。请编写一个程序来解决此问题。

解题思路

题目中要我们处理的是一棵 有根树,因此采用深度优先搜索(DFS)进行遍历,遍历时用数组记录每个节点的深度(即离根节点的距离)和父节点。每个节点的第k个祖先可以转化为它的深度向上跳2^i步(i为二进制位数),转化为二进制的形式,依次判断每个位上是否为1,为1则向上跳2^i步。

代码实现
import sys
input = sys.stdin.readline

def dfs(u):
    global cur_depth, depth, fa
    depth[u] = cur_depth
    for v in graph[u]:
        if v != fa[u]:
            fa[v] = u
            cur_depth += 1
            dfs(v)
            cur_depth -= 1

def get_kth_ancestor(u, k):
    while k > 0 and depth[u] > 0:
        t = k
        i = 0
        while t > 1:
            t //= 2
            i += 1
        if depth[u] >= 2 ** i:
            u = ancestor[u][i]
            k -= 2 ** i
        else:
            u = fa[u]
            k -= 1
    return u

# 读取数据
n, q = map(int, input().split())
graph = [[] for _ in range(n + 1)]
for i in range(n - 1):
    u, v = map(int, input().split())
    graph[u].append(v)
    graph[v].append(u)

# 预处理
cur_depth = 0  # 当前深度(离根节点的距离)
depth = [0] * (n + 1)  # 每个节点的深度
fa = [0] * (n + 1)  # 父节点
dfs(1)
max_depth = max(depth)
ancestor = [[0] * (max_depth + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
    ancestor[i][0] = fa[i]
for j in range(1, max_depth + 1):
    for i in range(1, n + 1):
        ancestor[i][j] = ancestor[ancestor[i][j - 1]][j - 1]

# 处理询问
for i in range(q):
    u, k = map(int, input().split())
    print(get_kth_ancestor(u, k))
    ```
    
    返回的是markdown格式的代码片段,在网页中展示如下:
    
    
```python
import sys
input = sys.stdin.readline

def dfs(u):
    global cur_depth, depth, fa
    depth[u] = cur_depth
    for v in graph[u]:
        if v != fa[u]:
            fa[v] = u
            cur_depth += 1
            dfs(v)
            cur_depth -= 1

def get_kth_ancestor(u, k):
    while k > 0 and depth[u] > 0:
        t = k
        i = 0
        while t > 1:
            t //= 2
            i += 1
        if depth[u] >= 2 ** i:
            u = ancestor[u][i]
            k -= 2 ** i
        else:
            u = fa[u]
            k -= 1
    return u

# 读取数据
n, q = map(int, input().split())
graph = [[] for _ in range(n + 1)]
for i in range(n - 1):
    u, v = map(int, input().split())
    graph[u].append(v)
    graph[v].append(u)

# 预处理
cur_depth = 0  # 当前深度(离根节点的距离)
depth = [0] * (n + 1)  # 每个节点的深度
fa = [0] * (n + 1)  # 父节点
dfs(1)
max_depth = max(depth)
ancestor = [[0] * (max_depth + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
    ancestor[i][0] = fa[i]
for j in range(1, max_depth + 1):
    for i in range(1, n + 1):
        ancestor[i][j] = ancestor[ancestor[i][j - 1]][j - 1]

# 处理询问
for i in range(q):
    u, k = map(int, input().split())
    print(get_kth_ancestor(u, k))