https://www.acmicpc.net/problem/11437
11437번: LCA
첫째 줄에 노드의 개수 N이 주어지고, 다음 N-1개 줄에는 트리 상에서 연결된 두 정점이 주어진다. 그 다음 줄에는 가장 가까운 공통 조상을 알고싶은 쌍의 개수 M이 주어지고, 다음 M개 줄에는 정
www.acmicpc.net
문제 제목 그대로 LCA 문제입니다. 일반적인 DFS로는 시간초과가 발생할 것 같아서 DP와 결합된 LCA알고리즘을 활용하여 풀이하였습니다.
import sys
from collections import defaultdict
from math import log, ceil
sys.setrecursionlimit(10 ** 6)
# sys.stdin = open("input.txt", "r")
input = sys.stdin.readline
graph = defaultdict(list)
n = int(input())
h = ceil(log(n) / log(2)) + 1
# 각 정점의 깊이
depth = [0] * (n + 1)
# parent[i][j]: i번 노드의 2 ^ j승번째 부모 노드
parent = [
    [0] * (h)
    for _ in range(n + 1)
]
for _ in range(n - 1):
    n1, n2 = tuple(map(int, input().split()))
    graph[n1].append(n2)
    graph[n2].append(n1)
def dfs(cur, d, pa):
    depth[cur] = d
    parent[cur][0] = pa
    for next_node in graph[cur]:
        if next_node != pa and depth[next_node] == 0:
            dfs(next_node, d + 1, cur)
def lca(a, b):
    # 항상 b가 더 깊게
    if depth[a] > depth[b]:
        a, b = b, a
    # 높이 맞추기
    for i in range(h - 1, -1, -1):
        if (1 << i) <= depth[b] - depth[a]:
            b = parent[b][i]
    if a == b:
        return a
    # 최소 공통 부모를 찾는 과정
    for i in range(h - 1, -1, -1):
        if parent[a][i] != parent[b][i]:
            a = parent[a][i]
            b = parent[b][i]
    return parent[a][0]
# 깊이와 부모노드 기록
dfs(1, 1, 0)
# 부모 노드들을 기록한다.
for i in range(1, h):
    for j in range(1, n + 1):
        parent[j][i] = parent[parent[j][i - 1]][i - 1]
m = int(input())
for _ in range(m):
    a, b = tuple(map(int, input().split()))
    print(lca(a, b))'문제 해결 > BOJ' 카테고리의 다른 글
| [백준] 벽 부수고 이동하기 2 (0) | 2023.02.22 | 
|---|---|
| [백준] 감시 (0) | 2023.02.21 | 
| [백준] 당근 훔쳐 먹기 (0) | 2023.02.20 | 
| [백준] 정복자 (0) | 2023.02.19 | 
| [백준] 같이 눈사람 만들래? (0) | 2023.02.18 |