공부혜옹

백준 1068번 트리 본문

공부합시다/Algorithm

백준 1068번 트리

Blair06 2021. 4. 20. 02:38

트리 

시간 제한메모리 제한제출정답맞은 사람정답 비율

2 초 128 MB 21823 5301 4166 25.887%

문제

트리에서 리프 노드란, 자식의 개수가 0인 노드를 말한다.

트리가 주어졌을 때, 노드 하나를 지울 것이다. 그 때, 남은 트리에서 리프 노드의 개수를 구하는 프로그램을 작성하시오. 노드를 지우면 그 노드와 노드의 모든 자손이 트리에서 제거된다.

예를 들어, 다음과 같은 트리가 있다고 하자.

현재 리프 노드의 개수는 3개이다. (초록색 색칠된 노드) 이때, 1번을 지우면, 다음과 같이 변한다. 검정색으로 색칠된 노드가 트리에서 제거된 노드이다.

이제 리프 노드의 개수는 1개이다.

입력

첫째 줄에 트리의 노드의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에는 0번 노드부터 N-1번 노드까지, 각 노드의 부모가 주어진다. 만약 부모가 없다면 (루트) -1이 주어진다. 셋째 줄에는 지울 노드의 번호가 주어진다.

출력

첫째 줄에 입력으로 주어진 트리에서 입력으로 주어진 노드를 지웠을 때, 리프 노드의 개수를 출력한다.


트리 탐색문제이다. 어떤 노드를 지운다면 그 하위 자식노드들까지 모두 삭제되고, 남은 트리의 노드들 중 리프노드는 몇개냐를 묻는 문제였다. 

 

풀이방법은 간단하다. 원래 트리의 리프노드를 모두 세고, 삭제할 노드의 자식노드들 중 리프노드의 갯수를 빼면된다.

1. 원래 트리의 리프노드를 센다.
2. 삭제하고자 하는 노드(del)의 부모 노드가 del이외의 다른 자식노드를 가지고 있는지 확인한다
-> 자식노드가 없을경우 삭제한 노드이외에 한개의 리프노드(부모)가 추가로 생겨나기 때문
3. dfs 재귀 탐색을 이용해 del의 자식노드들을 탐색하며 리프노드의 갯수를 파악한다.
4-1. 부모가 또다른 자식노드가 있을 경우 전체 리프노드갯수 - del의 리프노드갯수
4-2. 부모가 또다른 자식이 없을 경우 전체 리프노드갯수 - del의 리프노드 갯수 + 1

 

트리탐색을 많이 안해봐서 꼭 풀어보고 싶었던 문제다. 뭔가 간단하고 훨씬 효율적인 풀이방법이 있을것 같지만 탐색에 약한 나는 주먹구구식으로 밀었다...기본적인 탐색도 못하면서 탐색 응용 문제를 풀려니 애를 좀 먹었지만 문제를 따라가며 구현하면 어렵지 않게 풀 수 있는 문제였다. 다만 중간중간 변수 컨트롤을 실수해서 여러번 오답을 제출했다 역시 기본기가 중요함을 또다시 깨닫고 간다.......

#include <iostream>
#include <vector>
using namespace std;
 

int n;
int root;
int del;
int totalCnt = 0;
int cnt =0;
bool hasleaf = true;
vector<int> v(51);
bool haschild[51];

void func(int idx){
    for(int i=0; i<n; i++){
        if(v[i] == idx ){
            haschild[idx] = true;
            func(i);
        }
    }
    if(haschild[idx] == false){
        cnt++;
    }
}
int main() {
    
    cin >> n;
    v.resize(n);
    for(int i=0;i<n;i++){
        cin >> v[i];
        if(v[i] == -1){
            root = i;
        }
    }
    cin >> del;
    //root이면 0 출력
    if(v[del] == -1){
        cout << 0;
        return 0;
    }
    //지우려는 노드의 부모가 다른자식이 있는지 판별
    for(int i=0;i<n;i++){
        //v[del]->부모인덱스
        if(v[del] == v[i]){
            if(del != i){
                hasleaf = false;
            }
        }
    }
    for(int i=0; i<n; i++){
        int isthere = 0;
        for(int j=0; j<n; j++){
            if(v[j] == i){
                isthere = 1;
                break;
            }
        }
        if(isthere == 0){
            totalCnt++;
        }
    }
    func(del);
    
    if(hasleaf){
    //부모노드가 삭제할 노드이외의 자식노드를 보유하지않을 경우
        totalCnt = totalCnt - cnt + 1 ;
    }else{
        totalCnt = totalCnt - cnt;
    }
  
    cout << totalCnt << endl;
    return 0;
}

 

 

반응형

'공부합시다 > Algorithm' 카테고리의 다른 글

백준 2250번 트리의 높이와 너비  (0) 2021.04.20
백준 11437번 LCA  (0) 2021.04.20
백준 1981번 배열에서 이동  (0) 2021.04.13
백준 4256번 트리  (0) 2021.04.13
백준 1074번 Z  (0) 2021.04.13
Comments