[Algorithm] 다익스트라(Dijkstra) 알고리즘
다익스트라(Dijkstra) 알고리즘은 네비게이션 길 찾기나 네트워크 라우팅 등 실생활에서 가장 많이 활용되는 알고리즘 중 하나다. 그래프 내의 특정 한 정점에서 다른 모든 정점까지의 최단 경로를 찾는 것이다.
알고리즘 동작 단계
다익스트라는 크게 4단계의 반복으로 이루어진다.
- 출발점 설정: 시작 노드를 지정하고 해당 노드의 거리를
0으로 설정한다. - 거리 배열 초기화: 시작점을 제외한 모든 노드까지의 거리를 아주 큰 값(
INF)으로 설정한다. - 최단 거리 노드 선택: 아직 방문하지 않은 노드 중에서 현재 최단 거리가 가장 짧은 노드를 선택한다.
- 경로 갱신: 선택한 노드를 거쳐 인접 노드로 가는 거리와 기존에 저장된 거리를 비교하여 더 짧은 값을 저장한다.
구현 방법
다익스트라의 성능은 “가장 가까운 노드를 어떻게 찾는가”에 달려 있다.
- 단순 반복문 사용: 매번 모든 노드를 확인하므로 $O(V^2)$의 시간이 걸린다. (V는 노드의 수)
- 우선순위 큐(PriorityQueue) 사용: 거리가 짧은 노드를 즉시 뽑아낼 수 있어 $O(E \log V)$로 훨씬 빠르다. (E는 간선의 수)
C# 코드
using System;
using System.Collections.Generic;
class Solution
{
public int solution(int N, int[,] road, int K)
{
int answer = 0;
int INF = 10000000; // 충분히 큰 값 설정
int[] dist = new int[N + 1];
bool[] visited = new bool[N + 1];
// 1. 거리 배열 초기화
for (int i = 1; i <= N; i++) dist[i] = INF;
dist[1] = 0;
// 2. 다익스트라 알고리즘 수행
for (int i = 0; i < N; i++)
{
int minDistance = INF;
int u = -1;
// 아직 방문하지 않은 노드 중 가장 가까운 노드 선택
for (int j = 1; j <= N; j++)
{
if (!visited[j] && dist[j] < minDistance)
{
minDistance = dist[j];
u = j;
}
}
if (u == -1) break; // 더 이상 갈 수 있는 곳이 없음
visited[u] = true;
// 선택된 노드(u)를 거쳐가는 경로가 더 짧은지 확인
for (int r = 0; r < road.GetLength(0); r++)
{
int start = road[r, 0];
int end = road[r, 1];
int weight = road[r, 2];
if (start == u && dist[end] > dist[u] + weight)
{
dist[end] = dist[u] + weight;
}
else if (end == u && dist[start] > dist[u] + weight)
{
dist[start] = dist[u] + weight;
}
}
}
// 3. K 시간 이하인 마을 카운트
for (int i = 1; i <= N; i++)
{
if (dist[i] <= K) answer++;
}
return answer;
}
}
주의사항
다익스트라 알고리즘에는 한 가지 제약 조건이 있다.
“가중치(거리/시간)에 음수가 있으면 안 된다”
다익스트라는 “현재 가장 짧은 경로를 찾았다면, 그것이 최단 경로다”라는 그리디(Greedy) 원리를 따른다. 하지만 음수 가중치가 있다면, 나중에 더 작은 값이 나타나 기존의 최단 경로 가정을 깨뜨릴 수 있기 때문이다.
댓글남기기