Programming/Note

Prim ~ Dijkstra (BOJ1197 최소 스패닝 트리, BOJ1753 최단경로)

dododoo 2020. 2. 3. 16:28

https://www.acmicpc.net/problem/1197

 

1197번: 최소 스패닝 트리

첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이 가중치 C인 간선으로 연결되어 있다는 의미이다. C는 음수일 수도 있으며, 절댓값이 1,000,000을 넘지 않는다. 최소 스패닝 트리의 가중치가 -2147483648보다 크거나 같고, 2147483647보다 작거나 같은 데

www.acmicpc.net

#include <iostream>
#include <vector>
#include <queue>
#include <utility>
using namespace std;

int main()
{
    ios_base::sync_with_stdio(false);

    int V, E;
    cin >> V >> E;
    vector<vector<pair<int, int>>> adj(V+1);
    for (int i = 0; i != E; ++i) {
        int u, v, c;
        cin >> u >> v >> c;
        adj[u].push_back(make_pair(c, v));
        adj[v].push_back(make_pair(c, u));
    }

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    vector<int> selected(V+1);
    long long int total_cost = 0;

    pq.push(make_pair(0, 1));
    while (!pq.empty()) {
        auto [cost, v] = pq.top();
        pq.pop();
        if (selected[v]) {
            continue;
        }
        selected[v] = 1; 
        total_cost += cost;

        for (const auto& p : adj[v]) {
            if (!selected[p.second]) {
                pq.push(p);
            }
        }
    }
    cout << total_cost;

    return 0;
}

==========================================================================================

https://www.acmicpc.net/problem/1753

 

1753번: 최단경로

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1≤V≤20,000, 1≤E≤300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1≤K≤V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두

www.acmicpc.net

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
using PII = pair<int, int>;

int main()
{   
    ios_base::sync_with_stdio(false);
    
    int V, E;
    cin >> V >> E;
    int source;
    cin >> source;
    
    vector<vector<PII>> adj(V+1);
    for (int i = 0; i != E; ++i) {
        int s, d, w;
        cin >> s >> d >> w;
        adj[s].push_back(make_pair(w, d));
    }

    // Dijkstra using min heap: O(ElogV)
    vector<int> selected(V+1, -1);
    priority_queue<PII, vector<PII>, greater<PII>> pq;
    pq.push(make_pair(0, source));
    while (!pq.empty()) {
        const auto [w, v] = pq.top();
        pq.pop();
        if (selected[v] != -1) {
            continue;
        }
        selected[v] = w;
        for (const auto p : adj[v]) {
            if (selected[p.second] == -1) {
                pq.push(make_pair(w + p.first, p.second));
            }
        }
    }

    for (int i = 1; i != V+1; ++i) {
        if (const int cost = selected[i]; cost != -1) {
            cout << cost << '\n';
        } else {
            cout << "INF\n";
        }
    }

    return 0;
}

 

매우 유사하다.

 

차이점:

priority queue의 노드가 다르다. Prim은 해당 edge의 cost를 포함하고, Dijkstra는 path의 total cost를 포함한다.