2250
백준 2250번
Link: 2250번: 트리의 높이와 너비
문제 설명
이번엔 DFS 문제다.
문제 보고나서 트리 그리는 규칙 이해하는데만 한참 걸린것 같다.
아무튼 이해하고 나서 트리를 직접 그려가면서 규칙을 찾아봤는데,
-
우선 루트부터 찾은 다음 시작
-
루트 기준으로 왼쪽 방향으로 DFS시 만나는 가장 마지막 노드가 트리의 가장 왼쪽 노드
-
루트 기준으로 오른쪽 방향으로 DFS시 만나는 가장 마지막 노드가 트리의 가장 오른쪽 노드
-
루트 왼쪽 자식에서 오른쪽으로 DFS시 만나는 가장 마지막 노드가 루트 바로 왼쪽 노드
-
루트 오른쪽 자식에서 왼쪽으로 DFS시 만나는 가장 마지막 노드가 루트 바로 오른쪽 노드
이렇게 5가지 규칙을 찾았다.
이 규칙대로 트리를 만들고 문제를 풀어보려 했는데, 생각처럼 되지 않았다.
이 5가지 말고 내가 놓치고 있는 부분이 무엇인지 계속 생각해봤는데, 한가지 큰 부분을 놓치고 있었다.
이 트리를 그리는 규칙이 트리를 inorder 방식으로 탐색하는 순서와 같다는 점.
이 규칙 찾는데 하루는 더 걸린것 같다.
찾고 나니 푸는데 걸리는 시간은 순식간이었다.
트리의 각 노드들의 레벨만 구하면 되니까.
이 문제 알고리즘 분류가 DFS, 트리였는데 BFS를 넣어야 되지 않나 하는 생각도 들었다.
레벨 찾는데 사용한 알고리즘이 BFS였기 때문.
풀고 나니 나에게 실망스러웠는데, 그새 inorder, preorder, postorder 방식으로 트리 탐색하는 알고리즘을 까먹었다는 점 때문이다.
평소에 잘 알고 있었다면 트리 그리는 규칙 보자마자 아 이거 루트 찾아서 inorder로 탐색하면 끝나는 문제구나 했을텐데…
아무튼 늦게라도 떠올랐다는것 자체는 신기할 따름이다.
아직 갈길이 멀다는 생각밖에 안든다…
정답 코드
//
// Created by Keith_Lee on 21/02/2019.
//
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
struct Node{
int num = -1;
int left = 0;
int right = 0;
int parent = -1;
int level = -1;
int location = 0;
};
int N;
int lastLevel = 0; // 트리 최대 레벨
int place = 1;
Node nodeTree[10001]; // 입력따라 트리 저장할 공간
bool visit[10001] = {false, };
void inOrder(int start){
if(!visit[nodeTree[start].left]){
inOrder(nodeTree[start].left);
}
nodeTree[start].location = place++;
visit[start] = true;
if(!visit[nodeTree[start].right]){
inOrder(nodeTree[start].right);
}
}
void BFS(Node start){ // 각 노드들의 레벨을 찾는다.
int level = 1;
queue<Node> Queue;
vector<Node> nodes;
Queue.push(start);
while(!Queue.empty()){
nodes.clear();
while(!Queue.empty()){
Node temp = Queue.front();
Queue.pop();
nodes.push_back(temp);
}
for(int i=0; i<nodes.size(); i++){
Node current = nodes[i];
nodeTree[current.num].level = level;
if(current.left != -1){
Queue.push(nodeTree[current.left]);
}
if(current.right != -1){
Queue.push(nodeTree[current.right]);
}
}
level++;
}
}
int main(){
visit[0] = true;
cin >> N;
int nodeNum;
int leftChild;
int rightChild;
for(int i=1; i<=N; i++){
cin >> nodeNum >> leftChild >> rightChild;
nodeTree[nodeNum].num = nodeNum;
if(leftChild == -1){
nodeTree[nodeNum].left = 0;
}
else{
nodeTree[nodeNum].left = leftChild;
nodeTree[leftChild].parent = nodeNum;
}
if(rightChild == -1){
nodeTree[nodeNum].right = 0;
}
else{
nodeTree[nodeNum].right = rightChild;
nodeTree[rightChild].parent = nodeNum;
}
}
int root = 0;
for(int i=1; i<=N; i++){
if(nodeTree[i].parent == -1){
root = nodeTree[i].num;
break;
}
}
BFS(nodeTree[root]); // 각 노드의 레벨을 지정한다.
inOrder(root);
for(int i=1; i<=N; i++){
if(lastLevel < nodeTree[i].level){
lastLevel = nodeTree[i].level;
}
}
int maxWidth = 0;
int maxLevel = 0;
vector<int> levels;
for(int i=1; i<=lastLevel; i++){
levels.clear();
for(int j=1; j<=N; j++){
if(nodeTree[j].level == i){
levels.push_back(nodeTree[j].location);
}
}
sort(levels.begin(), levels.end());
int width = levels[levels.size()-1] - levels[0] + 1;
if(maxWidth < width){
maxLevel = i;
maxWidth = width;
}
}
cout << maxLevel << ' ' << maxWidth << '\n';
return 0;
}