https://www.acmicpc.net/problem/1167
문제
트리의 지름이란, 트리에서 임의의 두 점 사이의 거리 중 가장 긴 것을 말한다. 트리의 지름을 구하는 프로그램을 작성하시오.
입력
트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지 매겨져 있다.
먼저 정점 번호가 주어지고, 이어서 연결된 간선의 정보를 의미하는 정수가 두 개씩 주어지는데, 하나는 정점번호, 다른 하나는 그 정점까지의 거리이다. 예를 들어 네 번째 줄의 경우 정점 3은 정점 1과 거리가 2인 간선으로 연결되어 있고, 정점 4와는 거리가 3인 간선으로 연결되어 있는 것을 보여준다. 각 줄의 마지막에는 -1이 입력으로 주어진다. 주어지는 거리는 모두 10,000 이하의 자연수이다.
출력
첫째 줄에 트리의 지름을 출력한다.
예제 입력 1
5
1 3 2 -1
2 4 4 -1
3 1 2 4 3 -1
4 2 4 3 3 5 6 -1
5 4 6 -1
예제 출력 1
11
우선 결론적으로, 트리의 지름에 대해 알아야 풀 수 있는 문제다.
처음에는 1을 루트노드로 잡고 DFS를 돌려서 가장 먼 거리의 노드를 구하면 그 노드까지의 거리가 트리의 지름이겠다 싶었는데, 풀다보니 "도대체 어떤 노드를 루트노드로 해줘야 가장 먼 거리의 노드까지의 거리가 트리의 지름이 될 것인가?"라는 문제에 봉착했다. 그러다가 임의의 노드(x) 하나를 루트노드로 잡고 거기서 가장 먼 거리의 노드를 구한 후, 구한 노드를 루트 노드로 잡고 거기서 다시 먼 노드를 구했을 때 구한 노드가 바로 전에 돌렸던 DFS에서의 루트노드라면 그 거리가 최장거리이지 않을까라는 생각을 하게 됐다. 왜냐하면 어쨌든 최장거리가 될 수 있는 후보들은 끝 노드와 끝 노드간의 거리들이기 때문이다. A가 만약 끝점이고, 여기서 가장 먼 거리의 노드가 B일 때 B에서 가장 먼 끝점도 A면 A와 B사이의 거리가 최장거리가 된다는 것. 근데 만약 B에서 가장 먼 거리의 노드가 A가 아니라면 A가 끝점이 아니거나, A까지의 거리보다 더 먼 거리를 가지는 끝점이 있거나 둘 중 하나가 되는 것이다.
그럼 처음에 내 맘대로 루트노드를 1로 잡고 DFS를 돌려서 가장 먼 거리의 노드를 찾고, 다시 그 노드를 루트노드로 잡고 DFS를 돌려서 찾은 노드가 전에 돌렸던 DFS의 루트노드와 같다면, 그 때 측정한 거리가 루트의 지름이다!는 것을 알 수 있는데, 이렇게 연속된 두 번의 DFS결과를 비교하며 트리의 지름을 찾는 방식은 비효율적일것 같았다. 막말로 DFS를 몇 번 돌리게 될지도 모르는건데..그래서 그냥 루트의 지름에 대해서 공부했다.
참고한 링크 : https://blog.myungwoo.kr/112
요악하자면, 처음에 임의의 노드 하나를 루트노드로 잡고 가장 먼 거리의 노드를 찾은 다음, 그 녀석을 다시 루트노드로 잡고 가장 먼 거리의 노드를 찾으면 그 노드와의 거리가 트리의 지름이란 말이다.
암튼 뭐..그래서 코드는 다음과 같다.
import sys
sys.setrecursionlimit(10**6) # RecursionError 방지
V = int(sys.stdin.readline())
Tree = [[] for i in range(V + 1)]
for i in range(V):
c = list(map(int, sys.stdin.readline().split()))
for j in range(1, len(c) - 1, 2):
Tree[c[0]].append([c[j], c[j + 1]]) # 각 노드에 연결된 노드와 간선의 길이 표현
def DFS(Tree, start_node, distance):
for node, dis in Tree[start_node]:
if not distance[node]: # node까지 가는 거리가 0이라면 (기록되지 않았다면)
distance[node] = distance[start_node] + dis # node까지 가는 거리 기록
DFS(Tree, node, distance)
distance = [0 for i in range(V + 1)]
DFS(Tree, 1, distance)
distance[1] = 0 # distance는 start_node에서 각 노드까지의 거리를 저장하는 리스트이므로, 자기 자신에서 출발해 자기 자신까지의 거리는 0으로 해야 함.
start_node, max_distance = -1, -1
# 무지성으로 max(distance)를 하면 가장 먼 거리는 알 수 있는데, 어떤 노드까지의 거리
# 인지는 모르게 돼서, 이렇게 선형탐색같은 방법으로 가장 먼 거리를 가지는 노드를 찾음
for i in range(1, V + 1):
if distance[i] > max_distance:
max_distance = distance[i]
start_node = i
distance = [0 for i in range(V + 1)]
DFS(Tree, start_node, distance)
distance[start_node] = 0 # distance는 start_node에서 각 노드까지의 거리를 저장하는 리스트이므로, 자기 자신에서 출발해 자기 자신까지의 거리는 0으로 해야 함.
print(max(distance))
이걸 풀면서 배운 것은 배열을 통한 트리의 표현방법과, 재귀를 통한 DFS방법.
트리의 지름도 조만간 정리해서 올려야지.
'ALGORITHM > 백준BOJ풀이' 카테고리의 다른 글
[백준] 1759 - 암호 만들기 by python (0) | 2021.12.01 |
---|---|
[백준] 9465 - 스티커 by python (0) | 2021.11.21 |
[백준] 2468 - 안전영역 python 풀이 (0) | 2021.11.15 |
[백준] 1806 - 부분합 Python풀이 (0) | 2021.10.01 |
[백준] 1343 - 폴리오미노 Python 풀이(파이썬) - replace 활용법 알아가자 (0) | 2021.09.28 |