방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶은데, 그것은 바로 임의로 주어진 두 정점은 반드시 통과해야 한다는 것이다.
세준이는 한번 이동했던 정점은 물론, 한번 이동했던 간선도 다시 이동할 수 있다. 하지만 반드시 최단 경로로 이동해야 한다는 사실에 주의하라. 1번 정점에서 N번 정점으로 이동할 때, 주어진 두 정점을 반드시 거치면서 최단 경로로 이동하는 프로그램을 작성하시오.
첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존재하며, 그 거리가 c라는 뜻이다. (1 ≤ c ≤ 1,000) 다음 줄에는 반드시 거쳐야 하는 두 개의 서로 다른 정점 번호 v1과 v2가 주어진다. (v1 ≠ v2, v1 ≠ N, v2 ≠ 1) 임의의 두 정점 u와 v사이에는 간선이 최대 1개 존재한다.
첫째 줄에 두 개의 정점을 지나는 최단 경로의 길이를 출력한다. 그러한 경로가 없을 때에는 -1을 출력한다.
4 6
1 2 3
2 3 3
3 4 1
1 3 5
2 4 5
1 4 4
2 3
7
👩🏫 다익스트라 알고리즘을 이용하면 쉽게 풀 수 있는 문제입니다.
이 문제에서는 임의의 두✌ 정점을 반드시 지나는 최단 경로를 구해야 합니다.
임의의 두 정점을 각각 V1, V2라고 할 때, 우리는 이 두 정점을 지나 정점 N으로 갈 수 있는 경우를 아래와 같이 두 가지로 생각해 볼 수 있습니다.
최단 거리를 구해야 하기 때문에 우리는 둘 중 더 작은 경로를 선택하면 됩니다.
1.
1->V1->V2->N
➡ (1번 노드에서V1로 가는 최단 거리 +V1번 노드에서V2로 가는 최단 거리 +V2번 노드에서N로 가는 최단 거리 )
2.1->V2->V1->N
➡ (1번 노드에서V2로 가는 최단 거리 +V2번 노드에서V1로 가는 최단 거리 +V1번 노드에서N로 가는 최단 거리 )
그리고, 이 문제의 그래프는 방향성이 없는 그래프입니다.
따라서 아래와 같은 사실을 통해 다익스트라 알고리즘의 실행 수를 줄일 수 있습니다!
1->V1==V1->1
1->V2==V2->1
import heapq
import sys
input = sys.stdin.readline
INF = sys.maxsize # 임의로 무한댓 값 정의
def dijkstra(start): # 다익스트라 함수
distance = [INF for _ in range(N+1)]
distance[start] = 0
hq = [(0, start)]
while hq:
dis, node = heapq.heappop(hq)
if distance[node] < dis: continue
for n, d in graph[node]:
if distance[n] > distance[node] + d:
distance[n] = distance[node] + d
heapq.heappush(hq, (distance[n], n))
return distance
N, E = map(int, input().split())
graph = {n : [] for n in range(1, N+1)}
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()) # 지나야 하는 임의의 두 정점
V1_distance = dijkstra(V1) # V1이 시작 정점인 경우의 각 최단 거리
V2_distance = dijkstra(V2) # V2이 시작 정점인 경우의 각 최단 거리
# 1 -> V1 -> V2 -> N과 1-> V2 -> V1 -> N 중 더 짧은 경로 선택
route = min(V1_distance[1] + V1_distance[V2] + V2_distance[N],
V2_distance[1] + V2_distance[V1] + V1_distance[N])
print(route if route < INF else -1) # 거리가 INF라면 최단 경로가 존재하지 않음
graph : 각 간선의 거리를 저장하는 딕셔너리로, {a : [(b, c)]}는 a와 b를 연결하는 간선의 거리가 c라는 뜻입니다. distance : start 정점으로부터 각 노드로의 최단 거리를 저장하는 리스트입니다.📌 이 때, 유의해야 할 점이 있습니다!
임의의 두 정점을 지나는 최단 경로가 존재하지 않는다면, -1을 출력해야 한다는 것을 고려해야 합니다.
만약, 다익스트라를 사용하여 구한 최단 거리가 INF라면 임의의 두 정점을 지나 N으로 가는 거리가 존재하지 않는다는 의미이기 때문에 -1을 출력해줘야 합니다.