출시·고도화 중
Algorithm
다익스트라, 벨만-포드, 플로이드-워셜로 최단 경로를 구하고 크루스칼과 프림으로 최소 신장 트리를 만드는 방법을 정리합니다.
최단 경로 문제는 가중치 그래프에서 한 정점에서 다른 정점으로 가는 경로 중 가중치 합이 가장 작은 경로를 찾는 문제입니다. 최소 신장 트리(MST)는 무방향 그래프의 모든 정점을 사이클 없이 잇는 간선 집합 가운데 가중치 합이 가장 작은 것을 찾는 문제입니다. 다익스트라, 벨만-포드, 플로이드-워셜, 0-1 BFS, 크루스칼, 프림이 이 주제의 핵심 알고리즘입니다.
지도 길찾기, 네트워크 라우팅(OSPF, RIP), 게임의 경로 찾기, 배선과 배관 설계, 군집화처럼 실제 시스템 곳곳에서 이 알고리즘들이 돌아갑니다. 코딩 테스트와 기술 면접에도 자주 나오는데, 문제를 그래프로 모델링하고 가중치의 성질(음수가 있는지, 0과 1뿐인지, 그래프가 얼마나 밀집했는지)에 맞는 알고리즘을 고르는 능력을 보기 좋기 때문입니다.
먼저 BFS와 우선순위 큐(힙)에 익숙해진 뒤, 모든 알고리즘의 공통 연산인 완화(relaxation)를 이해하고 작은 그래프에서 다익스트라를 손으로 따라가 보는 것이 좋습니다. 이어서 음수 간선이 있을 때 벨만-포드가 필요한 이유를 확인하고, 유니온 파인드를 쓰는 크루스칼을 직접 구현해 봅니다. 마지막으로 상태를 넓혀 다익스트라를 돌리는 연습 문제로 응용력을 기릅니다.
모든 최단 경로 알고리즘은 'u를 거쳐 가면 v까지 더 짧은가'를 확인해 거리를 줄이는 완화 연산 위에 세워지며, 알고리즘마다 완화하는 순서만 다릅니다.
음수가 아닌 가중치에서 가장 가까운 정점을 이진 힙으로 꺼내 확정하며, O((V + E) log V) 시간에 한 출발점에서의 최단 거리를 모두 구합니다.
벨만-포드는 음수 간선을 허용하고 음수 사이클을 찾아내며, 플로이드-워셜은 O(V^3) 시간에 모든 정점 쌍 사이의 거리를 구합니다.
크루스칼은 간선을 가벼운 순서로 더하며 유니온 파인드로 사이클을 막고, 프림은 트리 하나를 가장 싼 간선으로 키웁니다. 둘 다 컷 성질 덕분에 옳은 답을 냅니다.
heapq로 (거리, 정점) 쌍을 거리가 짧은 순서대로 꺼내고, 꺼낸 거리가 이미 기록된 값보다 크면 낡은 항목이므로 건너뜁니다. 이웃까지의 거리가 줄어들면 값을 고치고 힙에 새 쌍을 넣습니다. python dijkstra.py로 실행하면 A에서 각 정점까지의 최단 거리 {'A': 0, 'B': 3, 'C': 1, 'D': 4}가 출력됩니다.
dijkstra.py
import heapq
def dijkstra(graph, source):
dist = {source: 0}
heap = [(0, source)]
while heap:
d, u = heapq.heappop(heap)
if d > dist[u]:
continue # stale entry
for v, w in graph[u]:
nd = d + w
if nd < dist.get(v, float("inf")):
dist[v] = nd
heapq.heappush(heap, (nd, v))
return dist
graph = {
"A": [("B", 4), ("C", 1)],
"B": [("D", 1)],
"C": [("B", 2), ("D", 5)],
"D": [],
}
print(dijkstra(graph, "A")) # {'A': 0, 'B': 3, 'C': 1, 'D': 4}
python dijkstra.py최단 경로와 최소 신장 트리 에 관해 묻고, 경험을 나누고, 의견을 주고받는 곳입니다.
아직 토론이 없습니다. 첫 이야기를 시작해 보세요.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.