[Python] boj no. 5719 : 거의 최단 경로
Problem
https://www.acmicpc.net/problem/5719
Idea
거의 최단 경로는 시작점과 도착점 사이의 최단 경로에 포함되는 간선을 사용하지 않은 최단 경로를 의미한다.
다익스트라 알고리즘과 너비 우선 탐색을 이용하여 다음과 같이 구현했다.
- 다익스트라 알고리즘을 이용해 시작점 S로부터 다른 모든 정점까지의 최소 비용 dist를 구한다.
- 도착점 D를 출발점으로 하여 BFS를 하며 최단 경로에 포함된 간선들을 제외한다. 탐색 중의 임의의 두 정점에서, 출발 지점(u)까지의 최소 비용 값에서 간선 가중치(w)를 뺐을 때 도착 지점(v)까지의 최소 비용 값이 된다면 S->D의 최단 경로에 포함된다(dist[u] - w == dist[v]).
- 2.를 통해 얻은 최단 경로에 포함된 간선들을 제외한 간선 집합을 이용하여 다시 다익스트라 알고리즘을 이용해 S부터 D까지의 최소 비용을 구한다.
Code
import sys
import heapq
from collections import deque
def dijkstra(start):
dist[start] = 0
heap = []
heapq.heappush(heap, (0, start))
while heap:
cd, cn = heapq.heappop(heap)
if cd > dist[cn]:
continue
for weight, nn in edge[cn]:
if cd + weight < dist[nn] and existed[cn][nn]:
dist[nn] = cd + weight
heapq.heappush(heap, (dist[nn], nn))
def bfs(start, end):
queue = deque()
queue.append(start)
while queue:
cn = queue.popleft()
for weight, nn in back_edge[cn]:
if dist[nn] == dist[cn]-weight and existed[nn][cn]:
existed[nn][cn] = False
queue.append(nn)
input = sys.stdin.readline
while True:
N, M = map(int, input().split())
if N == 0 and M == 0:
break
S, D = map(int, input().split())
edge = [[] for _ in range(N)]
back_edge = [[] for _ in range(N)]
existed = [[False for _ in range(N)] for _ in range(N)]
for _ in range(M):
U, V, P = map(int, input().split())
edge[U].append((P, V))
back_edge[V].append((P, U))
existed[U][V] = True
dist = [sys.maxsize for _ in range(N)]
dijkstra(S)
bfs(D, S)
dist = [sys.maxsize for _ in range(N)]
dijkstra(S)
if dist[D] == sys.maxsize:
dist[D] = -1
print(dist[D])