다익스트라
- 사용 : 특정노드에서 다른 모든 노드로의 최단 경로를 구함
- 전제조건 : weight가 음수일 수 없음
- 시간복잡도 :
동작원리
1. 출발노드 설정
2. 최단거리 테이블 초기화
3. 방문하지 않은 노드 중 최단거리가 가장 짧은 노드 선택
4. 해당 노드를 거쳐 다른 노드로 가는 비용 계산하여 최단 거리 테이블 갱신
5. 3번과 4번 반복
자다가도 바로 작성할 수 있을정도로 코드에 숙달되어있어야한다
출발 노드가 1일때, 다른 모든 노드로의 최단거리를 계산
노드번호 | 1 | 2 | 3 | 4 | 5 | 6 | 결과 |
---|---|---|---|---|---|---|---|
거리 | 0 | INF | INF | INF | INF | INF | 1선택 |
- | 2 | 5 | 1 | INF | INF | 4선택 | |
- | 2 | 4 | - | 2 | INF | 2선택 | |
- | - | 3 | - | 2 | 4 | 5선택 | |
- | - | 3 | - | - | 4 | 3선택 | |
- | - | - | - | 4 | 6선택 |
= 1번 노드에서 출발했을때
2,3,4,5,6번 노드까지의 최단경로는 각각
2,3,1,2,4 라는 뜻이다!
import sys
input = sys.stdin.readline
INF = int(1e9) #무한으로 10억 설정
# 노드 갯수, 간선 갯수 입력받기
n, m = map(int, input().split())
# 시작 노드 번호 입력받기
start = int(input())
# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트 만들기
graph = [[] for i in range(n+1)]
# 방문한 적이 있는지 체크하는 목적의 리스트 만들기
visited = [False] * (n+1)
# 최단 거리 테이블을 모두 무한으로 초기화
distance = [INF] * (n+1)
# 모든 간선 정보를 입력받기
for _ in range (m) :
a, b, c = map(int, input().split()) #a번 노드에서 b번 노드로 가는 비용이 c라는 의미
graph[a].append((b,c))
# 방문하지 않은 노드 중에서, 가장 최단거리가 짧은 노드의 번호를 반환
def get_smallest_node() :
min_value = INF
index = 0 # 가장 최단거리가 짧은 노드의 인덱스
for i in range(1, n+1) :
if distance[i] < min_value and not visited[i] :
min_value = distance[i]
index = i
return index
def dijkstra(start) :
#시작노드에 대해 초기화
distance[start] = 0
visited[start] = True
for j in graph[start] :#시작노드와 연결되어있다면, 거리를 기록한다
distance[j[0]] = j[1]
# 시작노드를 제외한 전체 n-1개의 노드에 대해 반복
for i in range(n-1) :
#현재 최단 거리가 가장 짧은 노드를 꺼내서, 방문 처리
now = get_smallest_node()
visited[now] = True
# 현재 노드와 연결된 다른 노드를 혹인
for j in graph[now] :
cost = distance[now] + j[1]
if cost < distance[j[0]] :
distance[j[0]] = cost
dijkstra(start)
# 모든 노드로 가기 위한 최단거리 출력
for i in range(1, n+1) :
# 도달할 수 없는 경우, 무한(Infinity)라고 출력
if distance[i] == INF :
print("INFINITY")
else :
print(distance[i])
시간복잡도 :
시간복잡도 :
현재 가장 가까운 노드를 O(V)만큼 연산해서 찾는게 아니라,
우선순위 큐를 이용하여 만큼 빠르게 꺼내서 찾는다.
우선순위큐
우선순위가 높은데이터를 가장 먼저 삭제. 삭제/삽입의 시간복잡도는
import heapq
import sys
input = sys.stdin.readline
INF = int(1e9)
# 노드의 갯수, 간선의 갯수 입력받기
n, m = map(int, input().split())
# 시작 노드 번호 입력받기
start = int(input())
# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
graph = [[] for i in range(n+1)]
# 최단거리 테이블을 모두 무한으로 초기화
distance = [INF] * (n+1)
# 모든 간선 정보를 입력받기
for _ in range :
a,b,c = map(int, input().split()) # a번 노드에서 b번 노드에서 가는 비용이 c라는 의미
graph[a].append((b,c))
def dijkstra(start) :
q = []
# 시작 노드로 가기 위한 최단경로는 0으로 설정하며, 큐에 삽입
heapq.heappush(q, (0, start))
distance[start] = 0
while q : # 큐가 비어있지 않다면
# 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
dist, now = heapq.headpop(q)
# 현재 노드가 이미 처리된 적이 있는 노드라면 무시
if distance[now] < dist :
continue
# 현재 노드와 연결된 다른 인접한 노드들을 확인
for i in graph[now] :
cost = dist + i[1]
# 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
if cost < distance[i[0]] :
distance[i[0]] = cost
heapq.heappush(q, (cost, i[0]))
dijkstra(start)
# 모든 노드로 가기 위한 최단거리 출력
for i in range(1, n+1) :
# 도달할 수 없는 경우, 무한(Infinity)라고 출력
if distance[i] == INF :
print("INFINITY")
else :
print(distance[i])
에서
~ 책 250P 다시 정리하기 ~