solved.ac Class 4레벨에 속한 문제이다.
문제 주소: https://www.acmicpc.net/problem/1167
1167번: 트리의 지름
트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지
www.acmicpc.net
문제 해석
문제 풀이
먼저 주어진 입력을 잘 받도록 코드를 구현해야 한다.
임의의 두 점 사이의 거리 중 가장 긴 것을 구하기 위해서는 일반적으로 모든 노드를 dfs 탐색해야 한다.
하지만 이 경우 주어진 노드의 수가 10,000개 이므로 n^2의 시간복잡도에서 통과할 수 없다.
이러한 트리의 지름을 구하는 문제는 임의의 노드로 부터 가장 먼 노드를 구한 뒤,
가장 먼 노드로부터 가장 먼 거리를 구해주면 답을 구할 수 있다.
즉, 2번의 dfs를 통해 주어진 문제를 해결할 수 있으므로, n의 시간복잡도로 문제를 해결할 수 있다.
문제 코드
import sys
input = sys.stdin.readline
def solve(adj, v):
visit = [0] * (v + 1)
far_node = 0
far_dist = 0
def dfs(cur, dist):
nonlocal visit
nonlocal far_node
nonlocal far_dist
if dist > far_dist:
far_node = cur
far_dist = dist
for next_node, next_dist in adj[cur]:
if visit[next_node] == 0:
visit[next_node] = 1
dfs(next_node, next_dist + dist)
visit[next_node] = 0
# 아무 점으로 부터 dfs를 통해 가장 먼 노드 찾기
visit[1] = 1
dfs(1, 0)
visit[1] = 0
# 가장 먼 노드에서 가장 먼 노드까지의 거리 구하기
far_dist = 0
visit[far_node] = 1
dfs(far_node, 0)
return far_dist
v = int(input())
adj = [[] for _ in range(v + 1)]
for _ in range(v):
temp = list(map(int, input().split()))
cur = temp[0]
for i in range((len(temp) - 2) // 2):
idx = i * 2 + 1
adj[cur].append((temp[idx], temp[idx + 1]))
print(solve(adj, v))
제출 결과
입력 부분을 잘 구현하자.
트리의 지름을 구하는 문제는 잊을만 하면 풀게 되는 것 같다..
'알고리즘 > BOJ' 카테고리의 다른 글
[백준/파이썬] 9370번 미확인 도착지 (0) | 2023.05.26 |
---|---|
[백준/파이썬] 20055번 컨베이어 벨트 위의 로봇 (0) | 2023.04.25 |
[백준/파이썬] 17144번 미세먼지 안녕! (0) | 2023.02.18 |
[백준/파이썬] 11054번 가장 긴 바이토닉 부분 수열 (0) | 2023.02.16 |
[백준/파이썬] 11725번 트리의 부모 찾기 (0) | 2023.02.16 |