본문 바로가기

알고리즘/백준

[백준] 11437번 : LCA

728x90

https://www.acmicpc.net/problem/11437

 

11437번: LCA

첫째 줄에 노드의 개수 N이 주어지고, 다음 N-1개 줄에는 트리 상에서 연결된 두 정점이 주어진다. 그 다음 줄에는 가장 가까운 공통 조상을 알고싶은 쌍의 개수 M이 주어지고, 다음 M개 줄에는 정

www.acmicpc.net

해당 문제는 특정 정점2개의 공통 조상을 찾는 문제입니다. 우선 각 정점을 깊이우선탐색으로 각각의 깊이를 구합니다.

구하려는 정점 2개의 공통조상을 찾기위하여 두 정점의 깊이를 맞춰주는데, 자기자신의 조상이 깊이우선탐색을 하면서 기록되었기 때문에 자기자신의 조상을 참조하면서 올라갑니다. 두 정점의 깊이가 일치할경우 같이 조상으로 올라가면서 같은 조상인지 판별 하면 됩니다. 해당문제는 O(n*m) 의시간복잡도를 갖습니다. 조상을 찾아가는 시간복잡도는 O(n)이고 쿼리의 개수가 주어지면 O(m) 이기 때문입니다.

 

import sys
sys.setrecursionlimit(int(1e5))
N = int(input()) # 노드의 개수
graph = [[] for _ in range(N+1)]

for _ in range(N-1):
    a ,b = map(int, input().split())
    graph[a].append(b)
    graph[b].append(a)
    
M = int(input()) # 쌍의 개수

d = [0 for _ in range(N+1)]
c = [False for _ in range(N+1)]
parent = [0 for _ in range(N+1)]

def dfs(rootnode, depth):
    d[rootnode] = depth
    c[rootnode] = True
    for childnode in graph[rootnode]:
        if not c[childnode]:
            parent[childnode] = rootnode
            dfs(childnode, depth+1)
            
            
def lca(a,b):
    # 노드의 깊이를 서로 맞춘다.
    while d[a] != d[b]: # a가 b보다 깊이가 큰경우
        if d[a] > d[b]:
            a = parent[a] # a가 거슬러 올라간다.
        else:
            b = parent[b] # b가 거슬로 올라간다.
            
    while a != b:
        a = parent[a]
        b = parent[b]
        
    return a

dfs(1,0)

for i in range(M):
    a, b = map(int, input().split())
    print(lca(a,b))
728x90

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 1016번 : 제곱 ㄴㄴ수  (0) 2023.08.04
[백준] 11438번 : LCA 2  (0) 2023.08.03
[백준] 2263번 : 트리의 순회  (0) 2023.08.01
[백준] 1197번 : 최소 스패닝 트리  (0) 2023.07.31
[백준] 17472번 : 다리 만들기 2  (0) 2023.07.31