June

DJIKSTRA

DJIKSTRA

다익스트라 알고리즘은 가중치가 있는 그래프에서 하나의 시작점으로부터 모든 정점까지의 최단 거리를 구하는 알고리즘이다.

특징

  • 음수 가중치가 없는 그래프에서만 사용 가능
  • 시간복잡도: O(E log V) (우선순위 큐 사용 시)
  • 그리디 알고리즘의 일종

사용 예시

  • 네비게이션 최단 경로
  • 네트워크 라우팅
  • 게임에서 캐릭터 이동 경로

동작 원리

핵심 아이디어

  1. 시작 정점의 거리를 0으로, 나머지는 무한대(INF)로 초기화
  2. 아직 방문하지 않은 정점 중 거리가 가장 짧은 정점을 선택
  3. 해당 정점을 거쳐 다른 정점으로 가는 거리가 더 짧으면 갱신 (relaxation)
  4. 모든 정점을 방문할 때까지 2-3 반복

구현

3.1 기본 구현 (인접 리스트 + 우선순위 큐)

c++
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int INF = 1e9;

vector<int> dijkstra(int start, vector<vector<pair<int, int>>>& graph) {
    int n = graph.size();
    vector<int> dist(n, INF);
    
    // 최소 힙: {거리, 정점}
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    
    dist[start] = 0;
    pq.push({0, start});
    
    while (!pq.empty()) {
        auto [curDist, cur] = pq.top();
        pq.pop();
        
        // 이미 처리된 정점이면 스킵
        if (curDist > dist[cur]) continue;
        
        // 인접 정점 탐색
        for (auto& [next, weight] : graph[cur]) {
            int newDist = curDist + weight;
            
            // 더 짧은 경로 발견 시 갱신
            if (newDist < dist[next]) {
                dist[next] = newDist;
                pq.push({newDist, next});
            }
        }
    }
    
    return dist;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    
    int V, E, start;
    cin >> V >> E >> start;
    
    // 인접 리스트: graph[u] = {{v1, w1}, {v2, w2}, ...}
    vector<vector<pair<int, int>>> graph(V + 1);
    
    for (int i = 0; i < E; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        graph[u].push_back({v, w});
        // 무방향 그래프면: graph[v].push_back({u, w});
    }
    
    vector<int> dist = dijkstra(start, graph);
    
    // 결과 출력
    for (int i = 1; i <= V; i++) {
        if (dist[i] == INF) cout << "INF\n";
        else cout << dist[i] << '\n';
    }
    
    return 0;
}

3.2 경로 추적 (최단 경로 역추적)

최단 거리뿐만 아니라 실제 경로도 알고 싶을 때 사용한다.

c++
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int INF = 1e9;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    
    int V, E, start, end;
    cin >> V >> E >> start >> end;
    
    vector<vector<pair<int, int>>> graph(V + 1);
    for (int i = 0; i < E; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        graph[u].push_back({v, w});
    }
    
    vector<int> dist(V + 1, INF);
    vector<int> parent(V + 1, -1);  // 경로 추적용
    
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    
    dist[start] = 0;
    pq.push({0, start});
    
    while (!pq.empty()) {
        auto [curDist, cur] = pq.top();
        pq.pop();
        
        if (curDist > dist[cur]) continue;
        
        for (auto& [next, weight] : graph[cur]) {
            int newDist = curDist + weight;
            
            if (newDist < dist[next]) {
                dist[next] = newDist;
                parent[next] = cur;  // 이전 정점 기록
                pq.push({newDist, next});
            }
        }
    }
    
    // 최단 거리 출력
    cout << dist[end] << '\n';
    
    // 경로 역추적
    vector<int> path;
    int cur = end;
    while (cur != -1) {
        path.push_back(cur);
        cur = parent[cur];
    }
    
    // 역순으로 출력 (start -> end)
    cout << path.size() << '\n';
    for (int i = path.size() - 1; i >= 0; i--) {
        cout << path[i] << ' ';
    }
    
    return 0;
}

Seoul, South Korea

jwsong5160@gmail.com

© 2026 Junwoo Song