[백준] 최소공통조상 LCA 11437번 (C++)

2025. 8. 24. 12:51·Algorithm
728x90

 

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

 

 

이 문제는 트리가 주어졌을때 두 노드를 기준으로 최소공통 조상을 찾는 문제이다.

최소공통조상 문제는 두 노드 사이의 거리를 빠르게 구하는 방법에서 자주 사용되는 문제이며 

다이나믹 프로그래밍을 사용하여 문제를 해결할 수 있다.

 

아래 예제를 통해 확인해보면

 

 

최소 공통 조상을 찾기 위한 방법으로

 

1. 기본적으로 트리 구조이기 때문에 dfs를 사용하여 노드의 부모를 저장한다.

2. 이후 두 노드를 기준으로 부모가 같아질때까지 계속해서 호출한다. 

 

이렇게 하면 같은 조상을 찾을 수 있다. 하지만 만약 같은 depth(깊이)에 있지 않고

다른 깊이에 있다면 얘기가 달라진다.

 

아래 그림을 한번 살펴보자

 

 

노드 12, 15를 기준으로 최소공통조상을 찾는다고 가정하면 답이 달라질 것이다. 만약 루트1의 부모가 1이라고 한다면

다른 깊이의 공통조상을 찾는다면 계속 1로 출력된다.

 

12노드가 2를 호출할 때 15노드가 4를 호출하기 때문에 최소 공통 조상을 찾을 수 없게 된다.

 

따라서 깊이를 저장하는 배열을 추가하면 이 문제를 쉽게해결할 수 있다.

 

1. 깊이가 다른 경우 더 깊은 깊은 노드를 1씩 낮추며 부모를 호출한다.

2. 두 노드가 같은 깊이(detph)일 경우 부모가 같아질때까지 부모를 호출한다.

 

정답코드

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
#define endl "\n"
#define MAX 1e9

struct coordinate {
    int x;
    int y;
    int r;
};

int dx[] = {0 ,0, -1, 0, 1, 1, -1, -1, 1};
int dy[] = {0, -1, 0, 1, 0, -1, 1, -1, 1};
int N, M;
vector<vector<int>> v(50001);
int parent[50001], lv[50001];

void dfs(int Node, int depth, int par) {			// 노드, 깊이, 부모
    lv[Node] = depth;
    parent[Node] = par;

    for(auto it : v[Node]) {
        if(it == par) continue;						// 이전 노드는 탐색했기 때문에 건너뜀
        dfs(it, depth+1, Node);
    }
}

void solve() {
    dfs(1, 0, 0);

    cin >> M;

    for(int i = 0; i < M; i++) {
        int a, b;
        cin >> a >> b;

        int l_depth = lv[a], r_depth = lv[b];

        while(l_depth > r_depth) {		// 왼쪽 노드깊이가 더 클 경우 올라가면서 깊이를 맞추기
            a = parent[a];
            l_depth--;
        }

        while(l_depth < r_depth) {		// 오른쪽 노드 깊이가 더 클 경우 올라가면서 깊이를 맞추기
            b = parent[b];
            r_depth--;
        }

        while(a != b) {					// 깊이가 같고 최소 공통 조상을 찾기 위해서 부모를 계속 호출
            a = parent[a];
            b = parent[b];
        }

        cout << a << endl;
    }
}

void input() {
    cin >> N;

    for(int i = 0; i < N-1; i++) {
        int a, b;
        cin >> a >> b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    input();
    solve();
}

 

728x90
저작자표시 (새창열림)

'Algorithm' 카테고리의 다른 글

[백준] 1068번 트리 (C++)  (0) 2025.08.26
[백준] 2234번 성곽 (C++)  (0) 2025.08.25
[백준] 20364번 부동산 다툼 (C++)  (0) 2025.08.23
[백준] 3055번 탈출 (C++)  (0) 2025.08.22
[백준] 11559번 Puyo Puyo (C++)  (0) 2025.08.21
'Algorithm' 카테고리의 다른 글
  • [백준] 1068번 트리 (C++)
  • [백준] 2234번 성곽 (C++)
  • [백준] 20364번 부동산 다툼 (C++)
  • [백준] 3055번 탈출 (C++)
쿨쿨.
쿨쿨.
  • 쿨쿨.
    All of the life
    쿨쿨.
  • 전체
    오늘
    어제
    • 분류 전체보기 (285) N
      • Programming (52) N
        • C, C++ (18)
        • Python (6)
        • Java (1)
        • HTML,CSS,JS (3)
        • SQL(DB) (13)
        • SpringBoot (8) N
        • Android (2)
        • CI,CD (1)
      • Algorithm (173)
        • Review (4)
      • Security (14)
        • WebHacking (3)
        • Websecurity (11)
      • OS (19)
        • Linux (12)
        • Mac os (2)
      • 머신러닝 (1)
      • CS(Computer Science) (12)
        • 컴퓨터 네트워크 (3)
        • 컴퓨터 구조 (1)
        • 인공지능 (8)
      • Docker (2) N
      • Dev Book Review (3)
        • Clean Code (1)
        • Effective Java (0)
        • Real MySQL (2)
      • SWM (1)
      • Review (6)
      • AWS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    에라토스테네스의 체
    트리
    시뮬레이션
    코딩
    백준
    다익스트라
    이분탐색
    우선순위 큐
    백트래킹
    재귀
    우선순위큐
    c언어
    그리디
    브루트포스
    구현
    다이나믹 프로그래밍
    Leviathan
    WebSecurity
    linux
    누적합
    그래프 이론
    비트마스킹
    DFS
    DP
    BFS
    Bandit
    정렬
    투포인터
    깊이우선탐색
    wargame
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.6
쿨쿨.
[백준] 최소공통조상 LCA 11437번 (C++)
상단으로

티스토리툴바