최소비용 구하기 2
다익스트라 알고리즘
다익스트라 알고리즘을 이용하는 문제이다. 다익스트라 알고리즘에 대한 포스팅은 아래의 두 문제에서 해놓았다.
‘최소비용 구하기 2’는 기본적인 다익스트라 알고리즘 문제에 경로 찾기가 추가된 형태이다.
먼저 다익스트라 알고리즘에 대해서 간략하게 집고 넘어가보자.
- 초기에 각 점의 시작점으로 부터의 최단거리는 inf이다.
- 시작점으로부터 뻗어나가는 간선을 탐색한다. 간선의 가중치 만큼 도착지에 업데이트 해준다.
- 아직 방문하지 않은 점들 중 최단거리가 최소인 점을 방문한다.
- 해당 점(a)으로 부터 뻗어나가는 간선을 탐색한다. 점’a’의 시작점으로부터 최단거리 + 간선의 가중치가 기존에 저장되어있던 최단거리보다 작을 때, 해당 노드의 최단거리를 업데이트한다.
- 이 과정을 모든 노드를 방문할 때 까지 반복하면, 모든 노드에 대해 시작점으로 부터 최단거리를 구할 수 있다.(단, 음의 가중치를 가지는 간선이 존재할 경우에는 사용할 수 없다.)
경로
시작점으로 부터 최단거리와 함께, 최소 비용을 갖는 경로에 포함되어 있는 도시의 정보도 찾아내야 한다.
이를 위해 ‘way’리스트를 만들었다. 음의 값을 가지는 노드는 존재하지 않음으로, 초기 값은 모두 -1로 저장해 두었다. 최단 경로를 탐색해 나가면서, ‘way’ 리스트에 최소 비용을 갖는 경로로 이동할 때, 해당 노드를 방문하기 이전 노드를 저장했다.
while point:
w_a, a = hq.heappop(point)
if a == end:
print(dp[a])
break
if a in bridge:
for x, w_x in bridge[a]:
if dp[x] > w_a + w_x:
#x의 최단거리 업데이트
dp[x] = w_a + w_x
#이전 노드 저장
way[x] = a
#heapq에 노드 추가
hq.heappush(point,[dp[x], x])
1 -> 3 -> 5 로 이동한 경우, way[5] = 3, way[3] = 1, way[1] = -1 이다. 이 정보를 사용해 5까지 어떻게 이동해 왔는지 역추적할 수 있다.
#경로 복원
memo_way=[]
while True:
memo_way.append(a+1)
a=way[a]
if a ==-1:
break
CODE
import sys
import heapq as hq
read=sys.stdin.readline
inf = sys.maxsize
n=int(read())
m=int(read())
bridge=dict()
for _ in range(m):
a,b,c=map(int,read().split())
a,b=a-1,b-1
if a not in bridge:
bridge[a]=[]
bridge[a].append((b,c))
start,end=map(int,read().split())
start,end=start-1,end-1
#이전 노드 저장
way=list(-1 for _ in range(n))
#start로부터 최단거리 저장
dp=list(inf for _ in range(n))
dp[start]=0
point=[[0, start]]
#heapq를 사용해 아직 방문하지 않은 점들 중 최단거리의 점 탐색
hq.heapify(point)
while point:
w_a, a = hq.heappop(point)
if a == end:
print(dp[a])
break
if a in bridge:
for x, w_x in bridge[a]:
if dp[x] > w_a + w_x:
#x의 최단거리 업데이트
dp[x] = w_a + w_x
#이전 노드 저장
way[x] = a
#heapq에 노드 추가
hq.heappush(point,[dp[x], x])
#경로 복원
memo_way=[]
while True:
memo_way.append(a+1)
a=way[a]
if a ==-1:
break
print(len(memo_way))
print(*memo_way[::-1])
틀린 부분이 있을 수 있습니다. 피드백 주시면 고치도록 하겠습니다!
감사합니다.👍
[꼭 다시 풀어보기]