728x90
시간 제한 2.5초(추가 시간 x), 메모리 제한 1024MB
# 조건
- 시청 공무원 마이크로는 과장으로부터 시에 있는 나무와 기둥의 길이와 가장 긴 가지의 길이를 파악하라는 업무 지시를 받았다.
- 마이크로는 ICPC Sinchon Winter Algorithm Camp에서 배운 트리 자료 구조를 이용하면 이 작업을 좀 더 수월하게 할 수 있으리라 판단했다.
- 마이크로는 트리의 기둥과 가지를 분류하기 위해 기가 노드를 추가로 정의하였다.
- 기가 노드는 루트 노드에서 순회를 시작했을 때, 처음으로 자식 노드가 $2$개 이상인 노드다.
- 기둥-가지를 줄여 기가 노드라 이름 붙였다. 위 그림에서 기가 노드는 $4$번 노드다.
- 단, 리프 노드가 1개인 경우 리프 노드가 동시에 기가 노드가 되며, 루트 노드가 동시에 기가 노드인 경우도 가능하다.
- 마이크로는 시의 나무를 트리 자료 구조로 옮겼다.
- 그런데 과장이 마이크로에게 또 다른 업무를 지시했다!
- 너무 바쁜 마이크로를 대신해 트리의 기둥과 가장 긴 가지의 길이를 측정하자.
입력
- 첫 번재 줄에는 노드의 개수 N(1<=N<=200,000)과 루트 노드의 번호 R(1<=R<=N)이 주어진다.
- 이후 N-1개의 줄에 세 개의 정수 a, b, d(1<=a, b<=N, a != b)가 주어진다.
- 이는 a번 노드와 b번 노드가 연결되어있으며 이 간선의 길이가 d(1<=d<=1000)임을 의미한다.
- 노드는 1번부터 N번까지 정수 번호가 매겨져 있으며 같은 간선은 여러 번 주어지지 않는다.
- 트리가 아닌 그래프는 입력으로 주어지지 않는다.
출력
- 나무의 기둥의 길이와 가장 긴 가지의 길이를 출력한다.
# 접근 방법
- 트리 구조를 활용하여 풀어준다.
- 이 때, 주의할 점은 주어지는 간선의 정보가 부모 - 자식순서가 아니라는 것과, 루트 노드가 기가 노드일 수도 있다는 것을 인지하자.
- 주어지는 트리의 정보를 tree리스트에 양방향으로 기록해준다.
- 이후, visted 배열을 생성하고 우선적으로 find_giga함수를 실행해준다.
- q에 루트 노드를 넣은 후 다음 노드를 탐색할 건데 이 때 기가 노드인지 판단하는 조건문은
- 기록되어 있는 길이가 3이상이거나, 길이가 2면서 루트 노드일 떄 기가 노드가 될 수 있다
- 양방향으로 기록하므로 루트 노드는 기가 노드가 아니라면 1개의 정보만 존재해야 되므로 2개가 되는 경우 기가 노드이다.
- 또한, 내부 노드의 경우 원래는 부모, 자식 총 2개의 정보가 있어야되지만 기가 노드의 경우 3개가 되므로 위와 같이 해주었다.
- 또한, 위의 조건을 만족하지 못하여 return 없이 탐색이 끝났다면, 리프 노드가 기가 노드인 경우이므로 -1을 리턴해준다.
- 위의 함수로 받은 return이 만약 -1이라면 visted의 가장 큰 값과 0을 출력해주고
- 그렇지 않다면 max_length 함수를 실행해준다.
- 일반적인 bfs와 같이 다음 노드까지의 거리를 누적해서 q에 담아주고, max_val이 현재 누적된 거리보다 작다면 갱신해주면 된다.
import sys
sys.stdin = open('input.txt')
input = sys.stdin.readline
from collections import deque
def find_giga(st):
q = deque()
q.append(st)
while q:
node = q.popleft()
if len(tree[node]) >= 3 or (len(tree[node]) == 2 and node == st):
return node
for next_node, val in tree[node]:
if not visited[next_node] and next_node != st:
visited[next_node] = visited[node] + val
q.append(next_node)
return -1
def max_length(st, R):
q = deque()
q.append((st, 0))
max_val = 0
while q:
node, val = q.popleft()
if val > max_val:
max_val = val
for next_node, next_val in tree[node]:
if not visited[next_node] and next_node != R:
visited[next_node] = 1
q.append((next_node, val + next_val))
return max_val
N, R = map(int, input().split())
tree = [[] for _ in range(N+1)]
for _ in range(N-1):
a, b, c = map(int, input().split())
tree[a].append((b, c))
tree[b].append((a, c))
visited = [0] * (N+1)
giga = find_giga(R)
if giga == -1:
print(max(visited), 0)
else:
print(visited[giga], max_length(giga, R))
728x90
'ALGORITHM > 자료구조' 카테고리의 다른 글
[백준 14675번] 파이썬 - 단절점과 단절선 (1) | 2024.01.28 |
---|---|
[백준 3986번] 파이썬 - 좋은 단어 (1) | 2023.12.18 |
[백준 5052번] 파이썬 - 전화번호 목록 (1) | 2023.10.20 |
[백준 20364번] 파이썬 - 부동산 다툼 (0) | 2023.10.07 |
[백준 4358번] 파이썬 - 생태학 (0) | 2023.10.05 |