입력 형식:
출력 형식:
예제 입력:
5 6
1
5 1 1
1 2 2
1 3 3
2 3 4
2 4 5
3 4 6
예제 출력:
0
2
3
7
INF
다익스트라(데이크스트라) 알고리즘이란?
최단 경로를 찾기 위한 알고리즘 양수여야 함 가장 가까운 정점을 선택 import sys
import heapq
def dijkstra(start, graph, V):
INF = float('inf')
# 모든 정점까지의 거리를 무한대로 초기화 (시작점 제외), 왜 무한대? => 못 가게 되면 무한대로 출력하기로 문제에서 정함
dist = [INF] * (V + 1)
# 시작점의 경우 0으로 초기화
dist[start] = 0
# (거리, 정점)을 저장할 우선순위 큐(최소 힙)
pq = []
# heapq.push(pq, (거리, 정점번호)) : 튜플의 첫번째 원소를 기준으로 정렬됨.
heapq.heappush(pq, (0, start))
while pq:
current_dist, u = heapq.heappop(pq) # 제일 짧은 거리에 있는 녀석이 튀어나옴
if current_dist > dist[u]:
continue # 이미 더 짧은 경로가발견 되었으므로 무시한다.
# 정점 u에서 뻗어나가는 모든 정점 v로의 거리 갱신 시도 (간선이 여러개 있을 수 있음)
for v, weight in graph[u]:
if dist[v] > current_dist + weight: # 만약 현재 거리 사전이 더 길다? 그럼
dist[v] = current_dist + weight # 아래처럼 갱신
heapq.heappush(pq, (dist[v], v))
return dist
def main():
V, E = map(int, sys.stdin.readline().rstrip().split())
K = int(sys.stdin.readline().rstrip())
# 그래프 초기화 (단방향 그래프)
graph = [[] for _ in range(V + 1)]
# E: 간선의 갯수 만큼 graph 초기화 값 설정
for _ in range(E):
# u에서 v로 가는 가중치 w만큼의 간선
u, v, w = map(int, sys.stdin.readline().rstrip().split())
graph[u].append((v, w))
distances = dijkstra(K, graph, V)
for i in range(1, V + 1):
if distances[i] == float('inf'):
print("INF")
else:
print(distances[i])
if __name__ == "__main__":
main()
입력 처리:
V, E = map(int, input().split())K = int(input())그래프 표현:
graph = [[] for _ in range(V + 1)]print로 뽑아낼 때 인덱스 0은 사용하지 않으니까-!간선 정보 저장:
u, v, w를 읽어 graph[u].append((v, w))로 저장 그래프 구성 표
| 정점 ( u ) | 연결된 정점 ( v )와 가중치 ( w ) | 설명 |
|---|---|---|
| 1 | (2, 2), (3, 3) | 1번에서 2번 가중치: 2, 3번 정점: 3 |
| 2 | (3, 4), (4, 5) | 2번에서 3번 가중치: 4, 4번 정점: 5 |
| 3 | (4, 6) | 3번에서 4번 가중치: 6 |
| 5 | (1, 1) | 5번에서 1번 가중치: 1 |
거리 배열 초기화:
dist = [INF] * (V + 1)
dist[start] = 0
→ 시작 정점 ( K )는 0, 나머지는 INF (아직 방문하지 않음)
우선순위 큐 초기화:
pq = []
heapq.heappush(pq, (0, start))
→ 튜플 (0, start)를 큐에 넣어, 시작 정점부터 처리
루프 기본 구조:
while pq:
current_dist, u = heapq.heappop(pq)
if current_dist > dist[u]:
continue
for v, weight in graph[u]:
if dist[v] > current_dist + weight:
dist[v] = current_dist + weight
heapq.heappush(pq, (dist[v], v))
설명:
우선순위 큐에서 가장 작은 거리 정점 선택:
heapq.heappop(pq)를 통해 (거리, 정점)을 꺼냄 (0, 1) → 정점 1, 거리 0이미 더 짧은 경로가 발견되었는지 확인:
if current_dist > dist[u]: continue current_dist는 현재 진행 중인 경로의 누적 거리를 의미하는건데, 우선순위 큐를 통해서 계속해서 START지점으로 부터의 각 지점으로까지의 거리가 계속하여 갱신되어 나옴.dist[u]의 경우에 u까지 이르게 되는 현재까지 발견된 최단거리를 의미하는데, 만약 current_dist가 이미 기록된 dist[u]보다 크다면, 그건 정점 u까지 도달하는더 짧은 경로가 이미 발견되었으므로, 지금 꺼낸 경로(current_dist)가 쓸모없게 되었다는 얘기임.전혀 없기에 그냥 무시(continue)하라는 것.현재 정점 u의 인접 정점 v들에 대해 거리 갱신:
dist[v] > current_dist + weight이면 dist[v]를 새로운 거리로 갱신하고, (dist[v], v)를 큐에 추가초기 상태
상태 변수 값 dist[INF, 0, INF, INF, INF, INF] pq[(0, 1)]
1. 정점 1 처리
pq.pop() → (0, 1) dist[2] = INF → 새 거리 0+2 = 2로 갱신 heapq.heappush(pq, (2, 2))dist[3] = INF → 새 거리 0+3 = 3로 갱신 | 정점 | 갱신 전 거리 | 계산된 거리 | 갱신 후 거리 | 큐 추가 항목 |
|---|---|---|---|---|
| 2 | INF | 0 + 2 = 2 | 2 | (2, 2) |
| 3 | INF | 0 + 3 = 3 | 3 | (3, 3) |
상태 변화
상태 변수 값 dist[INF, 0, 2, 3, INF, INF] pq[(2, 2), (3, 3)]
2. 정점 2 처리
pq.pop() → (2, 2) dist[3] = 3 → 계산된 거리 2+4 = 6 (갱신 불필요)dist[4] = INF → 계산된 거리 2+5 = 7로 갱신 heapq.heappush(pq, (7, 4))| 정점 | 갱신 전 거리 | 계산된 거리 | 갱신 후 거리 | 큐 추가 항목 |
|---|---|---|---|---|
| 3 | 3 | 2 + 4 = 6 | 3 (유지) | - |
| 4 | INF | 2 + 5 = 7 | 7 | (7, 4) |
상태 변화
상태 변수 값 dist[INF, 0, 2, 3, 7, INF] pq[(3, 3), (7, 4)]
3. 정점 3 처리
pq.pop() → (3, 3) dist[4] = 7 → 계산된 거리 3+6 = 9 (갱신 불필요)| 정점 | 갱신 전 거리 | 계산된 거리 | 갱신 후 거리 | 큐 추가 항목 |
|---|---|---|---|---|
| 4 | 7 | 3 + 6 = 9 | 7 (유지) | - |
상태 변화
상태 변수 값 dist[INF, 0, 2, 3, 7, INF] pq[(7, 4)]
4. 정점 4 처리
pq.pop() → (7, 4)
상태 변수 값 dist[INF, 0, 2, 3, 7, INF] pq[] (빈 상태)
→ 큐가 비었으므로 while 루프 종료
루프 종료 후 dist 배열 상태는 다음과 같음.
| 정점 번호 | 최단 거리 | 설명 |
|---|---|---|
| 1 | 0 | 시작 정점 (항상 0) |
| 2 | 2 | 경로: 1 → 2 (거리 2) |
| 3 | 3 | 경로: 1 → 3 (거리 3) |
| 4 | 7 | 경로: 1 → 2 → 4 (거리 2+5 = 7) |
| 5 | INF | 1번 정점에서 도달 불가 → "INF" 출력 |
최종 출력:
0
2
3
7
INF
입력 처리 및 그래프 구성:
다익스트라 알고리즘:
continue를 통해 건너뛰어 불필요한 연산을 줄임.루프 진행 및 우선순위 큐 변화:
dist 배열과 pq의 변화를 확인해 볼 것