(Dijkstra / Bellman-Ford / Floyd-Warshall)
그래프에서 어떤 정점에서 다른 정점까지 이동할 때의 최소 비용 경로를 의미한다.
이때 간선에 가중치(비용)가 있을 수 있고,
음수 간선이나 모든 정점 쌍의 거리를 요구하는 경우도 있다.
→ 따라서 입력 조건에 따라 다른 알고리즘을 선택해야 한다.
알고리즘 | 시작점 | 가중치 조건 | 음수 사이클 감지 | 시간복잡도 |
---|---|---|---|---|
Dijkstra | 단일 출발 | 양수만 허용 | ❌ 불가능 | O((V + E) log V) |
Bellman-Ford | 단일 출발 | 음수 O | ✅ 가능 | O(VE) |
Floyd-Warshall | 모든 정점 쌍 | 음수 O | ✅ 가능 (dist[i][i] < 0) | O(V³) |
import heapq
def dijkstra(graph, start):
n = len(graph)
distance = [float('inf')] * n
distance[start] = 0
pq = [(0, start)] # (비용, 노드)
while pq:
dist, now = heapq.heappop(pq)
if dist > distance[now]:
continue
for neighbor, cost in graph[now]:
new_dist = dist + cost
if new_dist < distance[neighbor]:
distance[neighbor] = new_dist
heapq.heappush(pq, (new_dist, neighbor))
return distance
# 예시
graph = {
0: [(1, 2), (2, 5)],
1: [(2, 1), (3, 2)],
2: [(3, 3)],
3: []
}
print("최단 거리:", dijkstra(graph, 0)) # [0, 2, 3, 4]
def bellman_ford(n, edges, start):
distance = [float('inf')] * n
distance[start] = 0
for i in range(n - 1):
for u, v, cost in edges:
if distance[u] != float('inf') and distance[u] + cost < distance[v]:
distance[v] = distance[u] + cost
# 음수 사이클 체크
for u, v, cost in edges:
if distance[u] != float('inf') and distance[u] + cost < distance[v]:
return None # 음수 사이클 존재
return distance
# 예시
edges = [(0, 1, 2), (1, 2, -3), (2, 3, 2), (3, 1, 1)]
print("최단 거리:", bellman_ford(4, edges, 0)) # None (음수 사이클)
dist[i][j] = i에서 j까지의 최단 거리
def floyd_warshall(n, graph):
dist = [[float('inf')] * n for _ in range(n)]
for i in range(n):
dist[i][i] = 0
for u, v, cost in graph:
dist[u][v] = cost
for k in range(n):
for i in range(n):
for j in range(n):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
return dist
# 예시
graph = [
(0, 1, 4),
(0, 2, 1),
(2, 1, 2),
(1, 3, 1),
(2, 3, 5)
]
dist = floyd_warshall(4, graph)
for row in dist:
print(row)
def has_negative_cycle(dist):
for i in range(len(dist)):
if dist[i][i] < 0:
return True
return False
알고리즘 | 목적 | 입력 구조 | 시간복잡도 | 음수 가중치 | 음수 사이클 감지 | 사용 상황 | 속도 체감 |
---|---|---|---|---|---|---|---|
Dijkstra | 한 정점 → 모든 정점 | 인접 리스트 + 우선순위 큐 | O((V + E) log V) | ❌ 안 됨 | ❌ 불가 | 지도, 경로 탐색 | 빠름 |
Bellman-Ford | 한 정점 → 모든 정점 | 간선 리스트 | O(VE) | ✅ 가능 | ✅ 가능 | 환율 계산, 음수 간선 | 느림 |
Floyd-Warshall | 모든 정점 쌍 | 인접 행렬 (2차원 DP) | O(V³) | ✅ 가능 | ✅ 가능 (dist[i][i] < 0 ) | 전체 거리 미리 계산 | 매우 느림 |
상황 | 추천 알고리즘 |
---|---|
양수 가중치, 빠른 단일 출발 | Dijkstra |
음수 간선 존재 | Bellman-Ford |
모든 정점 쌍 거리 필요 | Floyd-Warshall |
음수 사이클 판별 필요 | Bellman-Ford, Floyd-Warshall |