【模板】单源最短路径(标准版)

124 阅读1分钟

👉 “Offer 驾到,掘友接招!我正在参与2022春招打卡活动点击查看 活动详情

P4779 【模板】单源最短路径(标准版)

题目描述

给定一个 nn 个点,mm 条有向边的带非负权图,请你计算从 ss 出发,到每个点的距离。 数据保证你能从 ss 出发到任意点。

输入格式

第一行为三个正整数 n,m,sn, m, s。 第二行起 m 行,每行三个非负整数 ui,vi,wiu_i, v_i, w_i ,表示从uiu_iviv_i有一条权值为wiw_i的有向边。

输出格式

输出一行 nn 个空格分隔的非负整数,表示 ss 到每个点的距离。

输入输出样例

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
0 2 4 3

#include<bits/stdc++.h>
using namespace std;

struct Dijkstra{
    using PII = pair<int,int>;
    int n;
    vector<vector<PII>> G;
    vector<int> dis;
    vector<bool> vis;
    
    void Init(int n){
        this->n = n;
        G.resize(n);
        dis.resize(n);
        vis.resize(n);
    }
    
    void add_Edge(int u, int v, int w){
        G[u].push_back( {v,w} );
    }
    
    vector<int> get_Dist(int s){
        for(int i = 0; i < n; i++) dis[i] = 2e9;
        dis[s] = 0;
        priority_queue<PII> pq;
        pq.push( {0,s} );
        while(pq.size()){
            auto u = pq.top().second; pq.pop();
            if(vis[u]) continue;
            vis[u] = true;
            for(auto t : G[u]){
                int v = t.first, d = t.second;
                if(dis[v] > dis[u] + d){
                    dis[v] = dis[u] + d;
                    pq.push( {-dis[v], v} );
                }
            }
        }        
        return dis;
    }
};

int main(){
    int n,m,s;
    cin >> n >> m >> s;
    Dijkstra dij;
    dij.Init(n + 1);
    while(m--){
        int u,v,w;
        cin >> u >> v >> w;
        dij.add_Edge(u,v,w);  
    }
    auto ans = dij.get_Dist(s);
    for(int i = 1; i < ans.size(); i++) cout << ans[i] << " ";
    cout << endl;
    return 0;
}