문제
트리(tree)는 사이클이 없는 무방향 그래프이다. 트리에서는 어떤 두 노드를 선택해도 둘 사이에 경로가 항상 하나만 존재하게 된다. 트리에서 어떤 두 노드를 선택해서 양쪽으로 쫙 당길 때, 가장 길게 늘어나는 경우가 있을 것이다. 이럴 때 트리의 모든 노드들은 이 두 노드를 지름의 끝 점으로 하는 원 안에 들어가게 된다.
이런 두 노드 사이의 경로의 길이를 트리의 지름이라고 한다. 정확히 정의하자면 트리에 존재하는 모든 경로들 중에서 가장 긴 것의 길이를 말한다.
입력으로 루트가 있는 트리를 가중치가 있는 간선들로 줄 때, 트리의 지름을 구해서 출력하는 프로그램을 작성하시오. 아래와 같은 트리가 주어진다면 트리의 지름은 45가 된다.
트리의 노드는 1부터 n까지 번호가 매겨져 있다.
입력
파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n-1개의 줄에 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 연결하는 두 노드 중 부모 노드의 번호를 나타내고, 두 번째 정수는 자식 노드를, 세 번째 정수는 간선의 가중치를 나타낸다. 간선에 대한 정보는 부모 노드의 번호가 작은 것이 먼저 입력되고, 부모 노드의 번호가 같으면 자식 노드의 번호가 작은 것이 먼저 입력된다. 루트 노드의 번호는 항상 1이라고 가정하며, 간선의 가중치는 100보다 크지 않은 양의 정수이다.
출력
첫째 줄에 트리의 지름을 출력한다.
예제 입력121 2 3 1 3 2 2 4 5 3 5 11 3 6 9 4 7 1 4 8 7 5 9 15 5 10 4 6 11 6 6 12 10 |
예제 출력45 |
풀이
DFS를 통해 트리의 지름을 추적하는 문제이다.
부모 노드에서 자식 노드 방향으로만 추적을 진행할 것이니 방향 그래프로 생성해준다.
방문 여부를 표시할 필요도 없고
입력도 부모 - 자식 - 가중치 순서로 주어지니 수월하게 진행할 수 있다.
이제 DFS 통해 지름을 추적한다.
트리의 지름은 무조건 왼쪽 최장 경로 + 오른쪽 최장 경로라고 할 수 있다.이진 트리가 아니기 때문에 한 정점에 3개 이상의 경로가 있을 수 있지만, 사고를 쉽게 하기 위해 왼쪽, 오른쪽이라 칭하겠다.
DFS로 리프 노드(최하단 노드)까지 내려간 뒤 해당 노드의 가중치를 리턴한다.그리고 자식 노드가 있는 부모 노드부터는 자식들의 경로들 중 가장 큰 두 것을 선택한다.두 것을 더한 것은 현재 노드를 기준으로 지름이 된다.어느 기준 노드의 지름이 가장 클 지 알 수 없으니 지름을 전역 변수로 하나 생성해두고 더 큰 지름이 나올 때마다 갱신해준다.상위 부모 노드로 갱신해줄 때에는 왼쪽과 오른쪽 경로 중 더 큰 것을 리턴해준다.
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
n = int(input())
tree = [[] for _ in range(n+1)]
maxDist = 0
for _ in range(n-1):
a,b,c = map(int,input().split())
tree[a].append((b,c))
def dfs(n,d):
left,right = 0,0
for toNode, w in tree[n]:
r = dfs(toNode,w)
if left <= right:
left = max(left,r)
else:
right = max(right,r)
global maxDist
maxDist = max(maxDist,left+right)
return max(left+d,right+d)
dfs(1,0)
print(maxDist)
'알고리즘 연습 > 트리' 카테고리의 다른 글
[🥇2 / 백준 2263 / 파이썬] 트리의 순회 (0) | 2022.04.10 |
---|---|
[🥇5 / 백준 1068 / 파이썬] 트리 (0) | 2022.01.30 |
[🥈1 / 백준 1991 / 파이썬] 트리 순회 (0) | 2021.12.04 |
[🥇3 / 백준 1167 / 파이썬] 트리의 지름 (2) | 2021.10.05 |
[🥈2 / 백준 11725 / 파이썬] 트리의 부모 찾기 (0) | 2021.10.05 |