BOJ 2250. 트리의 높이와 너비
1. 문제설명
- 임의의 이진 트리가 입력으로 주어질 때 너비가 가장 넓은 레벨과 그 레벨의 너비를 구하라
- 한 칸에는 하나의 노드만 존재할 수 있다.
- 어떤 노드의 왼쪽 자식 노드는 해당 노드보다 왼쪽에 있고, 그 반대 또한 해당 노드보다 오른쪽에 있어야 한다.
-
노드가 배치된 가장 왼쪽과 오른쪽 사이엔 아무 노드도 없이 비어있는 열은 없다.
- 문제 분류
- Graph, Tree, DFS
2. 알고리즘 설계
- 어떤 트리인지에 대한 이해는 이미지를 보면 이해 가능할 것이다.
- 문제를 읽어보면 inorder(left child-root-right child)로 탐색한다.
- inorder의 형태는 다음과 같다.
void inorder(int cur) { inorder(cur->left); print(cur); inorder(cur->right); }
- 여기서
print(cur)
를 대신해, 좌/우 인덱스의 위치를 구할 것이다.
- 재귀적인 특성으로 인해 트리의 각 레벨을 탐색하면서 위치 정보를 갱신할 수 있다.
- 이미지를 보면 한 칸에는 하나의 노드만 삽입될 수 있어,
idx
변수를 통해 따로 관리해야 한다.
- 이미지를 보면 한 칸에는 하나의 노드만 삽입될 수 있어,
- 이후에는 각 트리의 레벨에서 좌/우 값을 서로 빼준 값에 1을 더해 최댓값을 구해주면 된다.
- 맞왜틀을 시전할 수 있는 포인트
- 시작 노드는 무조건 1은 아니다.
- 2로 시작할 수도 3으로 시작할 수도 있다.
inorder(root, 1);
이 부분을 반드시 루트로 설정해야 코드가 잘 작동한다.
3. 전체 코드
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int SZ=10'002, INF=987654321;
int n, p, l, r, root, idx=1;
pii tree[SZ];
int low[SZ], high[SZ], is_root[SZ];
void inorder(int cur, int d) {
if(cur < 1) return;
inorder(tree[cur].first, d+1);
low[d] = min(low[d], idx);
high[d] = max(high[d], idx++);
inorder(tree[cur].second, d+1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> n;
fill(low, low+n+1, INF);
for(int i=1; i<=n; i++) {
cin >> p >> l >> r;
tree[p] = {l, r};
is_root[p]++;
if(l != 1) is_root[l]++;
if(r != 1) is_root[r]++;
}
for(int i=1; i<=n; i++)
if(is_root[i] == 1)
root = i;
inorder(root, 1);
int lv = 1, width = high[1] - low[1] + 1;
for(int i=2; i<=n; i++) {
int cmp = high[i] - low[i] + 1;
if(cmp > width) {
width = cmp;
lv = i;
}
}
cout << lv << ' ' << width;
return 0;
}