최단경로·MST
다익스트라
길마다 걸리는 시간이 다르면
출발지 S 에서 가게 E 까지 가장 빠르게 가는 시간을 찾습니다.
길 위의 숫자는 걸리는 시간(분)입니다. 곳 옆의 숫자는 지금까지 알려진 가장 빠른 시간입니다.
거리표 — 곳마다 지금까지 알려진 가장 빠른 시간(분)
0S
∞A
∞B
∞C
∞D
∞E
걸음이 가장 적은 길이 가장 빠른 길일까요? 먼저 골라 보세요.
확정한 곳 0곳
내 예상 · 실제 다르다 (8분 대 6분) → 달랐어요
S → A → B → D → E가장 빠른 길은 4구간으로 6분입니다. 걸음이 가장 적은 길은 3구간이고 S→B→D→E 8분, S→A→C→E 10분이었습니다.
- 확정하는 순서 — 가장 가까운 곳부터 하나씩. S 0분 → A 2분 → B 3분 → D 5분 → E 6분
- 고쳐 적기 — 확정한 곳에서 이어진 길로 이웃까지 시간을 계산해 더 짧을 때만 고친다. B는 5분에서 3분으로 줄었다
- 걸음과 시간 — 걸음이 가장 적은 길은 3구간으로 8분·10분, 가장 빠른 길은 4구간으로 6분
가장 가까운 곳부터 확정하고 이웃의 시간을 줄여 가는 방법 = 다익스트라.
걸음이 가장 적은 길 (S→B→D→E)8분
가장 빠른 길 (S→A→B→D→E)6분
격자 BFS 는 걸음 수가 같은 칸을 한 겹으로 봤습니다. 길마다 시간이 다르면 걸음이 적은 길이 가장 빠른 길이 아닐 수 있습니다.
시간이 0 이상이어야 확정을 믿을 수 있다
- 확정한 곳은 끝 — 가장 가까운 곳이다. 길이 모두 0분 이상이면 다른 곳을 거쳐 와도 더 짧아지지 않는다
- 음수 시간이 있으면 — S→A 1분, S→B 2분, B에서 A로만 가는 한 방향 길이 −3분이면 A는 1분에 확정했는데 실제로는 −1분이다
- ① 에서 먼 곳을 못 누른 이유 — 더 가까운 곳이 남아 있으면 그곳을 거쳐 더 짧게 오는 길이 있을 수 있다
- 걸리는 일 — 길마다 큐에 한 번 넣고 꺼내니 많아야 길 수 × log. 길이 100,000개면 약 1,660,964번, 1초 안에 끝난다
코드는 큐에서 가장 작은 거리를 꺼내는 반복이다
코드 위에 import heapq 한 줄이 있다고 치세요. 다음을 눌러 한 줄씩 넘기며 거리표와 큐가 바뀌는 걸 보세요.
거리표 — 곳마다 지금까지 알려진 가장 빠른 시간(분)
0S
∞A
∞B
∞C
∞D
∞E
큐 (거리, 곳) — 왼쪽이 먼저 나감
- (0, S)
다음을 눌러 한 줄씩 넘겨 보세요
dijkstra.py
- 1def dijkstra(graph, start):
- 2 dist = {v: float('inf') for v in graph}
- 3 dist[start] = 0
- 4 heap = [(0, start)]
- 5 while heap:
- 6 d, u = heapq.heappop(heap)
- 7 if d > dist[u]:
- 8 continue
- 9 for v, w in graph[u]:
- 10 if d + w < dist[v]:
- 11 dist[v] = d + w
- 12 heapq.heappush(heap, (d + w, v))
- 13 return dist
0 / 36
36스텝입니다. while·for 머리줄(5·9번)과 낡은 항목을 거르는 7번 줄은 건너뜁니다. 낡은 항목이 나올 때만 8번 줄이 켜집니다.
heapq.heappop(heap)— 큐에서 거리가 가장 작은 (거리, 곳)을 꺼낸다if d > dist[u]: continue— 지금 기록보다 큰 낡은 항목은 건너뛴다if d + w < dist[v]— 더 짧을 때만 고쳐 적고 큐에 넣는다(d + w, v)— 큐에는 거리를 앞에 둔다. 그래야 가장 가까운 곳부터 나온다
A–B 길이 1분이 아니라 4분이라면, S에서 E까지 가장 빠른 시간은 몇 분일까요?
다익스트라에서 틀리는 자리
if d > dist[u]: continue를 빼면 — 답은 같지만 낡은 항목의 이웃까지 다시 본다. 이 지도에서 길 확인이 14번에서 17번으로 늘어난다- 거리를 0 으로 시작하면 — 어떤 길도 “더 짧다”로 보이지 않아 아무것도 고쳐지지 않는다. 결과가 모두 0분이다. 처음 값은
float('inf') - 큐에
(v, d + w)순서로 넣으면 — 곳 이름순으로 꺼내져 “가까운 곳 먼저”가 깨진다. 답은 같지만 이 지도에서 8번 꺼내고 7번 고쳐 적는다(제대로면 7번·6번) - 음수 길이는 — 이 코드는 낡은 값을 고쳐 다시 큐에 넣어서 음수 길이 한두 개는 맞는 답을 낸다. 하지만 돌수록 시간이 줄어드는 순환이 있으면 끝나지 않는다. 실제로 2,000번 꺼내도 거리가 계속 줄었다
문제에서 이 말이 보이면
길마다 걸리는 시간·비용이 다르다최단 거리·최소 비용지도·네트워크
다음 장에서는 같은 계산을 두 번 하지 않는 메모이제이션을 봅니다.