반응형
트리의 지름 (가장 먼 곳의 가장 먼 곳)
(백준 1167 파이썬)
https://www.acmicpc.net/problem/1167
문제의 이해는 쉽지만 어떻게 풀어야 할지.. 방법을 떠올리기 어려웠다. (나만 그런 듯)
지하철을 떠올리면 이해하기 쉽다.
3호선과 7호선만 생각해보자.
그림을 보면 이해가 갈 것이다.
- 녹번역(임의의 역)에서 출발하여 가장 먼 역까지 간다.
- 곧, 녹번역에서부터 가장 거리가 먼 종점까지 갔다는 것이다.
- 그 종점에서 가장 거리가 먼 또 다른 종점까지 간다.
- 두 종점의 거리가 가장 먼 거리가 된다.
실제 문제로 돌아와서, 트리의 한 노드에서 가장 거리가 먼 노드까지 도달하는 방법을 생각해보자
DFS혹은 BFS를 이용할 수 있겠다. 뭘 이용하던 완전탐색만 하면 된다.
또는 다익스트라를 이용할 수도 있다.
풀어보자. 첫 출발은 1번 노드다.
파이썬 코드
# BFS
# input 받는 부분이 난잡할 수 있습니다. 암튼 이중리스트로 받음
import sys
from collections import deque
N = int(sys.stdin.readline())
graph = [[] for n in range(N+1)]
# graph[i] = [node, cost] i에서 node로 가는 비용 : cost
for n in range(N) :
edges = list(map(int, sys.stdin.readline().split()))
edges_ = edges[1:-1]
for i in range(len(edges_)) :
if i % 2 == 0 :
graph[edges[0]].append((edges_[i], edges_[i+1]))
def bfs(start) : # start 부터 가장 먼 노드와 거기까지의 거리를 매번 갱신하면서 돌기
check = [False]*(N+1)
far_node, far_dist = 0, 0
need_visit = deque([])
need_visit.append((start, 0))
while need_visit :
n, c = need_visit.popleft()
check[n] = True
for node_cost in graph[n] :
node, cost = node_cost
if not check[node] :
need_visit.append((node, cost + c))
if far_dist < cost + c :
far_node, far_dist = node, cost + c
return far_node, far_dist
fn, fd = bfs(1)
ffn, ffd = bfs(fn)
print(ffd)
# DFS (재귀방식)
# 원리는 비슷합니다.
import sys
sys.setrecursionlimit(1000000)
N = int(sys.stdin.readline())
graph = [[] for n in range(N+1)]
# graph[i] = [node, cost] i에서 node로 가는 비용 : cost
for n in range(N) :
edges = list(map(int, sys.stdin.readline().split()))
edges_ = edges[1:-1]
for i in range(len(edges_)) :
if i % 2 == 0 :
graph[edges[0]].append((edges_[i], edges_[i+1]))
check = [False]*(N+1)
far_node, far_dist = 0, 0
def dfs(start, dist) :
global far_node
global far_dist
check[start] = True
for node_cost in graph[start] :
node, cost = node_cost
if not check[node] :
dfs(node, dist + cost)
if dist > far_dist :
far_node, far_dist = start, dist
dfs(1, 0)
fn = far_node
check = [False]*(N+1)
far_node, far_dist = 0, 0
dfs(fn, 0)
print(far_dist)
# 다익스트라
# 다익스트라는 보통 최단거리 계산시 사용하지만, 어차피 table에 최장거리 노드도 표시된다.
import sys
import heapq
N = int(sys.stdin.readline())
graph = [[] for n in range(N+1)]
# graph[i] = [node, cost] i에서 node로 가는 비용 : cost
for n in range(N) :
edges = list(map(int, sys.stdin.readline().split()))
edges_ = edges[1:-1]
for i in range(len(edges_)) :
if i % 2 == 0 :
graph[edges[0]].append((edges_[i], edges_[i+1]))
INF = 9999999
def ds(start) :
check = [False]*(N+1)
heap = []
heapq.heappush(heap, (0, start)) # (비용, 노드) 순서로 푸쉬
table = [INF]*(N+1) # start 에서 table[i] 까지 거리
table[start] = 0
while heap :
c, n = heapq.heappop(heap)
if check[n] == True :
continue
for node_cost in graph[n] :
node, cost = node_cost
if c + cost < table[node] :
table[node] = c + cost
heapq.heappush(heap, (c + cost, node))
check[n] = True
far_dist = 0
far_node = 0
for n in range(N+1) :
if table[n] == INF :
continue
else :
if far_dist < table[n] :
far_node = n
far_dist = table[n]
return far_node, far_dist
fn, fd = ds(1)
print(ds(fn)[1])
한 문제로 여러가지 복습을 해서 좋았다 ㅎㅎ. 오래걸렸지만 ㅠㅠ
의외로 속도는 dfs가 제일 빨랐다.
세 가지 모두 자연스럽게 이용 가능하도록 노력해보자.
-dnlxo
반응형
'프로그래밍 > Python 알고리즘 문제' 카테고리의 다른 글
비트마스킹, DP문제 (백준 1480 파이썬) (4) | 2021.06.19 |
---|---|
활동 선택, 스케쥴링 문제 (그리디) (0) | 2021.06.08 |
탐색과정에서 시간이 오래걸릴 때 (0) | 2021.06.08 |
파이썬 예외 처리 기본 (0) | 2021.06.08 |
파이썬의 연산 시간에 대하여 (0) | 2021.06.08 |