https://www.acmicpc.net/problem/2250
2250번: 트리의 높이와 너비
첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다.
www.acmicpc.net
백준 - 트리의 높이와 너비 (2250번)
난이도 : Gold 2
알고리즘&자료구조 : DFS (깊이우선탐색)
★ 핵심 Idea ★
◎ 루트 노드를 기준으로, 트리의 각 깊이 별 노드의 최소 최대 위치를 DFS로 구한다.
< 전체 코드 >
import sys
input = sys.stdin.readline
class Tree():
def __init__(self, N):
self.tree = [(0, 0) for _ in range(N+1)]
is_root = [True] * (N+2)
for _ in range(1, N+1):
p, l, r = map(int, input().split())
self.tree[p] = (l, r)
is_root[l] = is_root[r] = False
for i in range(1, N+1):
if is_root[i]:
root = i
break
self.children = [[0, 0] for _ in range(N+1)]
self.edges = [[10000, -10000] for _ in range(N+1)]
self._dfs_count(root)
self._dfs_breadth(root, 1, 0)
widest = [1, 1]
for i in range(2, N+1):
cur = self.edges[i][1] - self.edges[i][0] + 1
if cur < 0:
break
if widest[1] < cur:
widest = [i, cur]
self.answer = widest
def _dfs_count(self, node):
cnt = 1
for i in range(2):
cur = 0 if self.tree[node][i] == -1 else self._dfs_count(self.tree[node][i])
self.children[node][i] = cur
cnt += cur
return cnt
def _dfs_breadth(self, node, depth, loc):
if loc < self.edges[depth][0]:
self.edges[depth][0] = loc
if loc > self.edges[depth][1]:
self.edges[depth][1] = loc
for i in range(2):
cnode = self.tree[node][i]
if cnode == -1:
continue
cloc = loc + (1 if i else -1) * (self.children[cnode][i^1] + 1)
self._dfs_breadth(cnode, depth+1, cloc)
if __name__ == '__main__':
tree = Tree(int(input()))
print(*tree.answer)
① "self.tree"에 각 노드의 왼쪽과 오른쪽 자식 노드를 기록하고, root 노드를 찾는다.
self.tree = [(0, 0) for _ in range(N+1)]
is_root = [True] * (N+2)
for _ in range(1, N+1):
p, l, r = map(int, input().split())
self.tree[p] = (l, r)
is_root[l] = is_root[r] = False
for i in range(1, N+1):
if is_root[i]:
root = i
break
② "_dfs_count" 함수를 통해, 각 노드의 오른쪽과 왼쪽 자식 노드들의 개수를 "self.children"에 저장한다.
def _dfs_count(self, node):
cnt = 1
for i in range(2):
cur = 0 if self.tree[node][i] == -1 else self._dfs_count(self.tree[node][i])
self.children[node][i] = cur
cnt += cur
return cnt
self.children = [[0, 0] for _ in range(N+1)]
self._dfs_count(root)
③ 루트노드의 위치를 0으로 두고,
0을 기준으로 각 노드가 존재하는 깊이에서의 위치가, 해당 깊이에서의 최솟값 혹은 최댓값이라면 "self.edges"에 저장한다.
def _dfs_breadth(self, node, depth, loc):
if loc < self.edges[depth][0]:
self.edges[depth][0] = loc
if loc > self.edges[depth][1]:
self.edges[depth][1] = loc
for i in range(2):
cnode = self.tree[node][i]
if cnode == -1:
continue
cloc = loc + (1 if i else -1) * (self.children[cnode][i^1] + 1)
self._dfs_breadth(cnode, depth+1, cloc)
self.edges = [[10000, -10000] for _ in range(N+1)]
self._dfs_breadth(root, 1, 0)
④ 가장 범위가 넓은 깊이와 범위의 크기를 찾고,
그 값들을 출력한다.
widest = [1, 1]
for i in range(2, N+1):
cur = self.edges[i][1] - self.edges[i][0] + 1
if cur < 0:
break
if widest[1] < cur:
widest = [i, cur]
self.answer = widest
print(*tree.answer)
'Algorithm' 카테고리의 다른 글
비드맨 (19590번) - 백준 (BOJ) (0) | 2023.09.07 |
---|---|
벽 부수고 이동하기 4 (16946번) - 백준 (BOJ) (1) | 2023.09.06 |
구두 수선공 (14908번) - 백준 (BOJ) (0) | 2023.09.04 |
돌 그룹 (12886번) - 백준 (BOJ) (0) | 2023.09.03 |
소가 길을 건너간 이유 4 (14464번) - 백준 (BOJ) (0) | 2023.09.01 |