2250번 : 트리의 높이와 너비
문제)
이진트리를 다음의 규칙에 따라 행과 열에 번호가 붙어있는 격자 모양의 틀 속에 그리려고 한다. 이때 다음의 규칙에 따라 그리려고 한다.
- 이진트리에서 같은 레벨(level)에 있는 노드는 같은 행에 위치한다.
- 한 열에는 한 노드만 존재한다.
- 임의의 노드의 왼쪽 부트리(left subtree)에 있는 노드들은 해당 노드보다 왼쪽의 열에 위치하고, 오른쪽 부트리(right subtree)에 있는 노드들은 해당 노드보다 오른쪽의 열에 위치한다.
- 노드가 배치된 가장 왼쪽 열과 오른쪽 열 사이엔 아무 노드도 없이 비어있는 열은 없다.
이와 같은 규칙에 따라 이진트리를 그릴 때 각 레벨의 너비는 그 레벨에 할당된 노드 중 가장 오른쪽에 위치한 노드의 열 번호에서 가장 왼쪽에 위치한 노드의 열 번호를 뺀 값 더하기 1로 정의한다. 트리의 레벨은 가장 위쪽에 있는 루트 노드가 1이고 아래로 1씩 증가한다.
아래 그림은 어떤 이진트리를 위의 규칙에 따라 그려 본 것이다. 첫 번째 레벨의 너비는 1, 두 번째 레벨의 너비는 13, 3번째, 4번째 레벨의 너비는 각각 18이고, 5번째 레벨의 너비는 13이며, 그리고 6번째 레벨의 너비는 12이다.
![](https://blog.kakaocdn.net/dn/cijESc/btsrh2DLFos/igS5ZypYk4ck3UYzqWCmn1/img.png)
우리는 주어진 이진트리를 위의 규칙에 따라 그릴 때에 너비가 가장 넓은 레벨과 그 레벨의 너비를 계산하려고 한다. 위의 그림의 예에서 너비가 가장 넓은 레벨은 3번째와 4번째로 그 너비는 18이다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때는 번호가 작은 레벨을 답으로 한다. 그러므로 이 예에 대한 답은 레벨은 3이고, 너비는 18이다.
임의의 이진트리가 입력으로 주어질 때 너비가 가장 넓은 레벨과 그 레벨의 너비를 출력하는 프로그램을 작성하시오
입력 :
첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다. 노드들의 번호는 1부터 N까지이며, 자식이 없는 경우에는 자식 노드의 번호에 -1이 주어진다.
출력 :
첫째 줄에 너비가 가장 넓은 레벨과 그 레벨의 너비를 순서대로 출력한다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때에는 번호가 작은 레벨을 출력한다.
풀이)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
int n;
int lft[10010], rgt[10010], depth[10010], pos[10010];
int parent[10010];
map<int, vector<int>> m;
int cnt = 1;
// 각 노드의 깊이를 찾는 함수
void dfs(int cur, int d)
{
if (cur == -1) return;
depth[cur] = d;
dfs(lft[cur], d + 1);
dfs(rgt[cur], d + 1);
}
// 각 노드의 가로 위치를 찾는 함수
void inorder(int cur)
{
if (cur == -1) return;
inorder(lft[cur]);
pos[cur] = cnt;
cnt++;
inorder(rgt[cur]);
}
// 루트 노드를 찾기 위한 함수
void find_parent(int cur, int prv)
{
if (parent[cur] != 0) return;
parent[cur] = prv;
find_parent(lft[cur], cur);
find_parent(rgt[cur], cur);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
int a, b, c;
for (int i = 0; i < n; i++)
{
cin >> a >> b >> c;
lft[a] = b;
rgt[a] = c;
}
// 루트 노드 찾기
for (int i = 1; i < n + 1; i++)
{
if (parent[i] == 0)
{
find_parent(i, 0);
}
}
int root = 0;
for (int i = 1; i < n + 1; i++)
{
if (parent[i] == 0)
{
root = i;
break;
}
}
// 루트노드를 기반으로 각 노드의 깊이 구하기
dfs(root, 1);
// 중위 순회를 통해, 각 노드의 가로 번호 구하기
inorder(root);
// 깊이를 기준으로 map에 가로값들을 넣어준다.
for(int i = 1; i < n + 1; i++)
{
m[depth[i]].push_back(pos[i]);
}
// 각 깊이에서 최대 너비 값을 구해야 하므로.
int ans_w = 0, ans_d = 0;
for (auto iter = m.begin(); iter != m.end(); iter++)
{
// 구하기 쉽게 정렬 한뒤
sort(iter->second.begin(), iter->second.end());
// 맨 앞 인자와 맨 뒤 인자만을 가지고 계산한다.
int d = *(iter->second.end() - 1) - *(iter->second.begin()) + 1;
// 최대 너비를 찾았다면 바로 갱신해준다.
// map은 정렬된 key 순서대로 저장되기 때문에
// 가장 먼저 나온 최대 너비가 최소 레벨(깊이)가 된다.
if (ans_w < d)
{
ans_w = d;
ans_d = iter->first;
}
}
cout << ans_d << " " << ans_w;
return 0;
}
|
cs |
출처 : https://www.acmicpc.net/problem/2250
2250번: 트리의 높이와 너비
첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다.
www.acmicpc.net
'Develop > 백준 (Cpp)' 카테고리의 다른 글
[백준] 1167번 : 트리의 지름 (C++) (0) | 2023.08.16 |
---|---|
[백준] 5639번 : 이진 검색 트리 (C++) (0) | 2023.08.16 |
[백준] 2263번 : 트리의 순회 (C++) (0) | 2023.08.15 |
[백준] 1475번 : 방 번호 (C++) (0) | 2023.08.15 |
[백준] 1531번 : 투명 (C++) (0) | 2023.08.15 |