728x90
https://www.acmicpc.net/problem/11438
11438번: LCA 2
첫째 줄에 노드의 개수 N이 주어지고, 다음 N-1개 줄에는 트리 상에서 연결된 두 정점이 주어진다. 그 다음 줄에는 가장 가까운 공통 조상을 알고싶은 쌍의 개수 M이 주어지고, 다음 M개 줄에는 정
www.acmicpc.net
백준 3584 <가장 가까운 공통 조상>
https://www.acmicpc.net/problem/3584 3584번: 가장 가까운 공통 조상 루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과
dev-diary-0717.tistory.com
백준 17435 <합성함수와 쿼리>
https://www.acmicpc.net/problem/17435 17435번: 합성함수와 쿼리 함수 f : {1, 2, ..., m}→{1, 2, ..., m}이 있다. 이때 fn : {1, 2, ..., m}→{1, 2, ..., m}을 다음과 같이 정의하자. f1(x) = f(x) fn+1(x) = f(fn(x)) 예를 들어 f4(1) =
dev-diary-0717.tistory.com
바로 이전에 포스팅했던 두 가지를 합쳐 풀 수 있는 문제입니다. 노드의 깊이를 맞춰줄 때에도 희소 배열을 이용해 빠르게 맞출 수 있고, 두 노드를 거슬러 올라가면서도 희소배열을 사용해 시간을 단축시킬 수 있습니다.
import sys
from collections import deque
from math import log2
def solution(N, M, edge_list, data_list):
# LCA 와 희소배열 이용
# 트리의 최대 깊이
max_depth = int(log2(N))+1
# 트리 / tree[i] = [i 의 자식들]
tree = [[] for _ in range(N+1)]
for node_1, node_2 in edge_list:
tree[node_1].append(node_2)
tree[node_2].append(node_1)
# 노드 깊이 기록 및 트리 정리
depth_list, tree = set_node_depth(tree, N)
# 희소 배열 / sparse_table[i][j] = j 노드의 2^(i) 위의 조상
sparse_table = [tree[:] for _ in range(max_depth)]
for i in range(1, max_depth):
for j in range(1, N+1):
# 조상 노드의 값이 -1 이면 기록하지 않음
if sparse_table[i-1][j] > 0:
sparse_table[i][j] = sparse_table[i-1][sparse_table[i-1][j]]
else:
sparse_table[i][j] = -1
# 데이터 순회
for node_1, node_2 in data_list:
# 노드 깊이 맞추기
node_1, node_2, depth = equalize_depth(node_1, node_2, depth_list, sparse_table)
# 두 노드가 같으면 출력
if node_1 == node_2:
print(node_1)
continue
# 두 노드를 2^n 만큼 거슬러 올라갔을 때 두 노드가 같지 않을 때까지 반복
for exp in range(max_depth-1, -1, -1):
if sparse_table[exp][node_1] != sparse_table[exp][node_2]:
# node_1 거슬러 올라가기
node_1 = sparse_table[exp][node_1]
# node_2 거슬러 올라가기
node_2 = sparse_table[exp][node_2]
# 끝까지 거슬러 올라갔을 때 부모가 공통 조상
print(sparse_table[0][node_1])
# 노드 깊이 기록 및 트리 정리 함수
def set_node_depth(tree, N):
# 정리된 트리 / fixed_tree[i] = i 의 부모 노드
fixed_tree = [-1 for _ in range(N+1)]
# BFS 사용을 위한 큐 / [노드, 깊이]
queue = deque([[1, 0]])
# 깊이 목록
depth_list = [-1 for _ in range(N+1)]
# 트리 순회
while True:
# 큐가 비면 리턴
if not queue:
return depth_list, fixed_tree
# 현재 노드
now_node, depth = queue.popleft()
# 현재 깊이 기록
depth_list[now_node] = depth
# 연결되어 있는 노드 큐에 삽입
for node in tree[now_node]:
# 깊이가 기록되어 있지 않을 때만
if depth_list[node] == -1:
queue.append([node, depth+1])
# 트리 정리
fixed_tree[node] = now_node
# 노드 깊이 맞추기
def equalize_depth(node_1, node_2, depth_list, sparse_table):
# 각 노드의 깊이
depth_1 = depth_list[node_1]
depth_2 = depth_list[node_2]
# 맞춰질 깊이
depth = min(depth_1, depth_2)
# 1 이 깊으면
if depth_1 > depth_2:
# 깊이의 차이
sub_depth = depth_1 - depth_2
# 차이를 이진법으로 표현
bin_sub_depth = list(reversed(bin(sub_depth)[2:]))
# 1을 두 깊이의 차이만큼 내림
for num_idx in range(len(bin_sub_depth)):
# num 이 1이면
if int(bin_sub_depth[num_idx]):
node_1 = sparse_table[num_idx][node_1]
# 2 가 깊으면
elif depth_1 < depth_2:
# 깊이의 차이
sub_depth = depth_2 - depth_1
# 차이를 이진법으로 표현
bin_sub_depth = list(reversed(bin(sub_depth)[2:]))
# 1을 두 깊이의 차이만큼 내림
for num_idx in range(len(bin_sub_depth)):
# num 이 1이면
if int(bin_sub_depth[num_idx]):
node_2 = sparse_table[num_idx][node_2]
return node_1, node_2, depth
N = int(sys.stdin.readline())
edge_list = [list(map(int, sys.stdin.readline().split())) for _ in range(N-1)]
M = int(sys.stdin.readline())
data_list = [list(map(int, sys.stdin.readline().strip().split())) for _ in range(M)]
solution(N, M, edge_list, data_list)
728x90
'Coding Test > BaekJoon_Python' 카테고리의 다른 글
백준 13511 <트리와 쿼리 2> Python (2) | 2024.01.01 |
---|---|
백준 3176 <도로 네트워크> Python (1) | 2023.12.30 |
백준 17435 <합성함수와 쿼리> Python (1) | 2023.12.28 |
백준 3584 <가장 가까운 공통 조상> Python (0) | 2023.12.27 |
백준 1766 <문제집> Python (0) | 2023.12.27 |