문제 풀이/문제 풀이(BOJ)

[Gold V] 최소비용 구하기 - 1916

풀뿌리 2024. 6. 5. 14:36

문제링크: https://www.acmicpc.net/problem/1916

 

다익스트라 알고리즘 문제이다.

 

다익스트라 알고리즘이란 음의 간선이 없는 노드들 사이에서 최단거리를 찾는 알고리즘이다. 

 

1. 입력 받기:
    입력: N, M
    for i = 1 to M:
        입력: u, v, cost

    입력: A, B

2. 그래프 초기화:
    adj = 빈 리스트[N+1]
    for i = 1 to M:
        adj[u].append((v, cost))
        adj[v].append((u, cost))  // 만약 무방향 그래프일 경우 (단방향 그래프인 경우 이 줄 생략)

3. 거리와 우선순위 큐 초기화:
    dist = [∞] * (N + 1)
    dist[A] = 0
    pq = 우선순위 큐
    pq.push((0, A))

4. 다익스트라 알고리즘 실행:
    while pq가 비어 있지 않은 동안:
        current_dist, current_node = pq.pop()
        if current_dist > dist[current_node]:
            continue

        for neighbor, weight in adj[current_node]:
            new_dist = current_dist + weight
            if new_dist < dist[neighbor]:
                dist[neighbor] = new_dist
                pq.push((new_dist, neighbor))

5. 결과 출력:
    출력: dist[B]

끝

 

이게 수도코드이다. 인접한 노드를 찾은 다음 연결하고 연결 된 도시의 비용들을 갱신한다. 목적지에 도착하기 까지의 방문한 이웃들에 대하여 모두 완료하고나면 종료된다.

 

이를 위해서는 항상 작은 값을 큐에서 꺼내올 필요가 있었고 이를 위해 힙 트리 구조를 사용하였다.

 

priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;

이게 해당 구조이다. 우선순위 큐에 벡터 컨테이너를 사용하였다.

 

아래는 위의 수도코드를 C++로 작성한 것이다.

 

#include <iostream>
#include <vector>
#include <queue>
#define INF 1e9

#define fastio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;

vector<vector<int>> Map;

int main() {
    fastio;
    int N, M;
    cin >> N >> M;
   
    vector<vector<pair<int, int>>> adj(N + 1);

    for (int i = 0; i < M; i++) {
        int u, v, cost;
        cin >> u >> v >> cost;
        adj[u].emplace_back(v, cost);
    }

    int start, arrive;
    cin >> start >> arrive;
    
    vector<int> dist(N + 1, INF);
    dist[start] = 0;

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    pq.push({ 0, start });

    while (!pq.empty()) {
        int current_dist = pq.top().first;
        int current_node = pq.top().second;
        pq.pop();

        if (current_dist > dist[current_node]) continue;

        for (auto& edge : adj[current_node]) {
            int neighbor = edge.first;
            int weight = edge.second;
            int new_dist = current_dist + weight;

            if (new_dist < dist[neighbor]) {
                dist[neighbor] = new_dist;
                pq.push({ new_dist, neighbor });
            }
        }
    }

    cout << dist[arrive] << endl;

    return 0;
}