ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 3548번 가장 가까운 공통 조상
    문제 풀이 2020. 8. 31. 17:58

    3584 가장 가까운 공통 조상


    문제


    루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과 같이 정의됩니다.

    -두 노드의 가장 가까운 공통 조상은, 두 노드를 모두 자손으로 가지면서 깊이가 가장 깊은(즉 두 노드에 가장 가까운) 노드를 말합니다.

    nca.png

    예를 들어  15와 11를 모두 자손으로 갖는 노드는 4와 8이 있지만, 그 중 깊이가 가장 깊은(15와 11에 가장 가까운) 노드는 4 이므로 가장 가까운 공통 조상은 4가 됩니다.

    루트가 있는 트리가 주어지고, 두 노드가 주어질 때 그 두 노드의 가장 가까운 공통 조상을 찾는 프로그램을 작성하세요


    입력


    첫 줄에 테스트 케이스의 개수 T가 주어집니다.

    각 테스트 케이스마다, 첫째 줄에 트리를 구성하는 노드의 수 N이 주어집니다. (2 ≤ N ≤ 10,000)

    그리고 그 다음 N-1개의 줄에 트리를 구성하는 간선 정보가 주어집니다. 한 간선 당 한 줄에 두 개의 숫자 A B 가 순서대로 주어지는데, 이는 A가 B의 부모라는 뜻입니다. (당연히 정점이 N개인 트리는 항상 N-1개의 간선으로 이루어집니다!) A와 B는 1 이상 N 이하의 정수로 이름 붙여집니다.

    테스트 케이스의 마지막 줄에 가장 가까운 공통 조상을 구할 두 노드가 주어집니다.


    출력


    각 테스트 케이스 별로, 첫 줄에 입력에서 주어진 두 노드의 가장 가까운 공통 조상을 출력합니다.



    풀이)

    단순히 어떤 노드끼리 연결되었는지 정보를 준 것이 아니라 부모-자식 노드 관계 정보를 준 문제여서

    주어진 정보를 이용해 그대로 트리를 만들어 풀면 된다.


    과정

    1. 트리를 만든다.


    (사용하는 배열들)

    int parent[i] // i 노드의 부모 노드 번호 저장하는 배열

    int depth[i] // i 노드의 트리 내에서의 깊이 저장하는 배열


    parent[]배열을 이용해 트리의 루트 노드 번호를 찾고, (루트 노드 번호는 그 노드의 부모 노드 번호와 일치할때의 번호)

    그리고 그 루트 노드부터 시작해 dfs로 각 노드들 깊이들을 확인해 depth[]에 저장


    ex) 트리 입력 예시

    n = 5

    (2 3)

    (3 4)

    (3 1)

    (1 5)

    (3 5) 일때,


    2. 공통 조상을 구할 두 노드의 트리 내 깊이를 확인한다.


         노드가 n1, n2라고 할때 depth[n1] , depth[n2] 확인


    3. 두 노드가 같은 깊이를 가질 때까지 한 노드를 그 노드의 부모로 바꿔준다.


    4. 깊이가 같아졌을 때 노드 번호가 똑같은지 확인 

                                 같은 번호가 아니라면, 두 노드들 모두 같은 번호가 될때까지 각자 부모 노드로 변경.


    5. 같은 노드 번호(= 최소 공통 조상)를 출력



    코드)


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
     
    int n;
    vector <int> adj[10001];
    int depth[10001];
    int parent[10001];
     
    void dfs(int node) {
        for (int i = 0; i < adj[node].size(); i++) {
            int next = adj[node][i];
            if (depth[next] == -1) {
                depth[next] = depth[node] + 1;
                dfs(next);
            }
        }
    }
    int main() {
        int test_case;
        scanf("%d"&test_case);
        while (test_case--)
        {
            scanf("%d"&n);
            int a, b;
            for (int i = 1; i <= n; i++) {
                parent[i] = i;
            }
            for (int i = 0; i < n-1; i++) {
                scanf("%d %d"&a, &b);
                parent[b] = a;
                adj[a].push_back(b);
            }
            int n1, n2;
            scanf("%d %d"&n1, &n2);
     
            for (int i = 1; i <= n; i++) {
                depth[i] = -1;
            }
     
            int root = 1;
            while (true)
            {
                if (root == parent[root]) break;
                root = parent[root];
            }
            depth[root] = 0;
            dfs(root);
            
            if (depth[n1] < depth[n2]) swap(n1, n2);//깊이가 깊은 노드를 n1으로
            
            while (depth[n1] != depth[n2]) //깊이가 같아질때까지
            {
                n1 = parent[n1];
            }
            if (n1 == n2) {
                printf("%d\n", n1);
                continue;
            }
            while (n1 != n2)
            {
                n1 = parent[n1];
                n2 = parent[n2];
            }
            printf("%d\n", n1);
     
            for (int i = 1; i <= n; i++) {
                parent[i] = -1;
                adj[i].clear();
            }
        }
        return 0;
    }
    cs


    댓글

Designed by Tistory.