문제
풀이
- 그래프가 주어진 후, 최단 경로를 구하는 문제 + 정점의 개수와 간선의 개수의 범위가 크므로
플로이드 워셜
보다는 다익스트라 알고리즘
으로 접근하는게 수월하다.
- 보통 다익스트라 알고리즘 문제는 입력값의 범위가 매우 커 시간초과가 날 수 있으니 python3보다는 pypy3를, 입력은 sys.stdin.readline으로 설정하면 해결 할 수 있다.
- 방향성이 없는 양방향 그래프 이므로 양방향에 대한 거리(비용)을 모두 입력받아야 한다.
- 세준이는 1번 정점에서 n번까지 최단 거리로 이동해야 하며 v1과 v2를 반드시 거쳐야 한다.
- v1과 v2는 != 1, v1 != v2, != n이다.
- 그럼 이동하는 방식은
1 -> v1 -> v2 -> n
or 1 -> v2 -> v1 -> n
이 두가지만 고려하면 된다.
- 최단 경로를 구해야하므로 위 두가지 방식중 최소값을 반환하면 답을 도출할 수 있다.
코드
import heapq
import sys
input = sys.stdin.readline
inf = int(1e9)
def dijkstra(k:int) -> list:
distance = [inf] * (n + 1)
queue = []
heapq.heappush(queue, (0, k))
distance[k] = 0
while queue:
dist, now = heapq.heappop(queue)
if distance[now] < dist:
continue
for i in graph[now]:
cost = dist + i[1]
if cost < distance[i[0]]:
distance[i[0]] = cost
heapq.heappush(queue, (cost, i[0]))
return distance
def solve() -> int:
result = []
lenth = dijkstra(1)
lenth_v1 = dijkstra(v1)
lenth_v2 = dijkstra(v2)
result.append(lenth[v1] + lenth_v1[v2] + lenth_v2[n])
result.append(lenth[v2] + lenth_v1[n] + lenth_v2[v1])
return min(result) if min(result) < inf else -1
if __name__ == '__main__':
n, e = map(int, input().split())
graph = [[] for _ in range(n+1)]
result = []
for _ in range(e):
a, b, c = map(int, input().split())
graph[a].append([b, c])
graph[b].append([a, c])
v1, v2 = map(int, input().split())
print(solve())
결과
출처 & 깃허브
BOJ 1504
GITHUB