ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 트리의 높이와 너비 (boj 2250)
    알고리즘 2020. 6. 3. 17:52
    728x90

    트리의 높이와 너비 문제는 각 노드마다 자식 노드의 번호를 2개 주고, 이를 이진트리로 만든 뒤 DFS하는 문제에요 (Postorder search)

     

    아래 코드를 보시면

    children 배열에 자식노드를, parent 노드에 부모 노드를 저장하여 이진트리를 구성했어요.

    그리고 빈 column 없이 트리를 구성해야한다는 점을 이용하면, 왼쪽 자식 서브 트리가 차지한 최대 column + 1 이 자기 자신의 노드 column index가 된다는 것을 알 수 있죠. 이후 오른쪽 자식노드의 maxIndex를 구하는 이유는 내 부모 노드의 위치를 결정해주어야 하기 때문이에요.

    DFS를 통해 재귀적으로 자식의 maxIndex 부터 알아가며 자기 자신의 위치를 결정하고, 그렇게 결정된 위치를 통해 레벨 별 최소 최대 인덱스를 적절히 계산하여 너비를 구해내면 답을 쉽게 찾을 수 있습니다.

     

    코드

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    
    #define INF 987654321
    
    int N;
    
    // 자식 노드 (first = 왼쪽 노드, second = 오른쪽 자식 노드)
    std::pair<int, int> children[10010];
    
    // 부모 노드
    int parent[10010];
    
    // 최종 결과 (first = 해당 레벨에서 가장 작은 column index, second = 해당 레벨에서 가장 큰 column index)
    std::pair<int, int> result[10010];
    
    // 트리 루트
    int root;
    
    /**
     * 트리 순회 함수
     * @param curNode 현재 방문하고 있는 노드
     * @param level  현재 방문하고 있는 노드의 레벨
     * @param startColumn 현재 노드가 가질 수 있는 최소 column index - 1     즉, 현재까지 노드로 차 있는 column index 라고 생각하면 좋음
     * @return 현재 노드가 구성하는 서브트리의 max column index
     */
    int DFS(int curNode, int level, int startColumn) {
        // 유효하지 않은 노드번호인 경우 startColumn 자체가 max column index
        if (curNode == 0)
            return startColumn;
    
        // 왼쪽 자식의 max column index 를 구함
        int left = DFS(children[curNode].first, level + 1, startColumn);
    
        // 나 자신은 왼쪽 자식의 max column index 바로 다음 것에 저장됨
        int position = left + 1;
    
        // 현재 level에서 나 자신이 가장 최소 index 이거나 최대 index 일 수 있으니 이를 업데이트
        result[level].first = std::min(result[level].first, position);
        result[level].second = std::max(result[level].second, position);
    
        // 오른쪽 자식의 maxIndex
        int right = DFS(children[curNode].second, level + 1, position);
        return right;
    }
    
    int main() {
        scanf("%d", &N);
    
        for (int n = 1; n <= N; n++) {
            int num, left, right;
            scanf("%d %d %d", &num, &left, &right);
            if (left == -1)
                left = 0;
    
            if (right == -1)
                right = 0;
    
            // 트리 구성
            // 노드 num 의 왼쪽 오른쪽 자식 노드를 세팅
            children[num].first = left;
            children[num].second = right;
    
            // 왼쪽 오른쪽 자식 노드 입장에서는 num이 부모 노드
            parent[left] = num;
            parent[right] = num;
    
            result[n].first = INF;
        }
    
        for (int n = 1; n <= N; n++) {
            // 부모가 없는 노드가 루트노드
            if (!parent[n]) {
                root = n;
                break;
            }
        }
    
        // DFS 돌리면 level 별로 최소 인덱스와 최대 인덱스가 저장되어 나옴
        DFS(root, 1, 0);
    
        int n1 = 0, n2 = 0;
        for (int n = 1; n <= N; n++) {
            // 최대 너비 찾기
            int width = result[n].second - result[n].first + 1;
            if (n1 < width) {
                n1 = width;
                n2 = n;
            }
        }
        printf("%d %d\n", n2, n1);
        return 0;
    }
    

    '알고리즘' 카테고리의 다른 글

    쿼드트리 (boj 1992)  (0) 2020.06.05
    별 찍기 11 (boj 2448)  (0) 2020.06.03
    수학은 너무 쉬워 (boj 2904)  (0) 2020.06.03
    MT 문제 (boj 10265)  (0) 2020.05.16
    위상정렬  (0) 2020.05.16

    댓글

Designed by Tistory.