【算法篇-圖論】dijkstra

一、適用條件

單源最短路問題、非負權圖

二、算法思想

三、樸素的dijkstra(鄰接矩陣存圖)

時間復雜度分析

O(v*v), 頂點的二次方

題目來源:https://www.acwing.com/problem/content/851/

  1. Dijkstra求最短路 I

給定一個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為正值。
請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出-1。
【輸入格式】
第一行包含整數n和m。
接下來m行每行包含三個整數x,y,z,表示點x和點y之間存在一條有向邊,邊長為z。
【輸出格式】
輸出一個整數,表示1號點到n號點的最短距離。
如果路徑不存在,則輸出-1。
【數據范圍】
1≤n≤500,
1≤m≤105,
圖中涉及邊長均不超過10000。
【輸入樣例】:
3 3
1 2 2
2 3 1
1 3 4
【輸出樣例】:
3

#include <bits/stdc++.h>
using namespace std;
const int maxn = 510;
const int INF = 0x3f3f3f;
int g[maxn][maxn], d[maxn];
bool vis[maxn];

void init(int n){
    for(int i=1; i<=n; i++)  // 初始化全部為不相連
        for(int j=1; j<=n; j++)
            g[i][j] = INF;
    for(int i=1; i<=n; i++){
        d[i] = INF;   // 最短距離初始化
        g[i][i] = 0;    // 防止有自環
        vis[i] = false;  // 標記點還未確定最短距離
    }
}

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    init(n);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        g[x][y] = min(g[x][y], z);  //重邊的話,選較小的權值
    }
    d[1] = 0;     // 起點,此處是頂點1
    for(int i=1; i<=n; i++){
        int u, minx = INF;   // u是距離起點最近的點
        for(int j=1; j<=n; j++)
            if(!vis[j] && d[j]<minx){
                minx = d[j];
                u = j;
            }
        vis[u] = true;
        for(int j=1; j<=n; j++) // 松弛 
            d[j] = min(d[j], d[u]+g[u][j]);  // d[j]相當于g[1][j]
    }
    if(d[n]==INF)  // n是終點,判斷是否連通
        printf("-1");
    else
        printf("%d", d[n]);
    return 0;
}

四、堆優化的dijkstra(鄰接表存圖)

題目來源:https://www.acwing.com/problem/content/852/

  1. Dijkstra求最短路 II

給定一個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為正值。
請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出-1。
【輸入格式】
第一行包含整數n和m。
接下來m行每行包含三個整數x,y,z,表示點x和點y之間存在一條有向邊,邊長為z。
【輸出格式】
輸出一個整數,表示1號點到n號點的最短距離。
如果路徑不存在,則輸出-1。
【數據范圍】
1≤n,m≤105,
圖中涉及邊長均不超過10000。
【輸入樣例】:
3 3
1 2 2
2 3 1
1 3 4
【輸出樣例】:
3

與上一題,區別是n與m的區別,此處是稀疏圖,上一題是稠密圖。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
const int INF = 0x3f3f3f;
struct edge{
    int from, to, cost;
};
vector<edge> G[maxn];
typedef pair<int, int> P; // first是距離,second是頂點,pair排序默認是先first,再是second
int d[maxn], n;

void dijkstra(int s, int t){
    priority_queue<P, vector<P>, greater<P> > Q;  // 小根堆
    for(int i=1; i<=n; i++)
        d[i] = INF;
    d[s] = 0;
    Q.push(P(0, s));
    while(!Q.empty()){
        P u = Q.top();
        Q.pop();
        int v = u.second; // 頂點 
        if(d[v]<u.first)  // 已經處理過了 
            continue;
        for(int i=0; i<G[v].size(); i++){  //松弛
            edge e = G[v][i];
            if(d[e.to]>d[v]+e.cost) {
                d[e.to] = d[v]+e.cost;
                Q.push(P(d[e.to], e.to));  // 更新后的結點信息
            }
        }
    }
    cout << d[t];
}

int main(){
    int m, x, y, z;
    cin >> n >> m;
    for(int i=1; i<=m; i++){
        cin >> x >> y >> z;
        G[x].push_back((edge){x, y, z});
    }
    dijkstra(1, n); 
    return 0;
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 生活大爆炸版石頭剪刀布 題目描述 石頭剪刀布是常見的猜拳游戲:石頭勝剪刀,剪刀勝布,布勝石頭。如果兩個人出拳一樣,...
    bbqub閱讀 471評論 0 0
  • 一些概念 數據結構就是研究數據的邏輯結構和物理結構以及它們之間相互關系,并對這種結構定義相應的運算,而且確保經過這...
    Winterfell_Z閱讀 5,893評論 0 13
  • 就本次期末考試我做一下簡要分析:本次考試參加考試的同學有51人,90分以上的有2人,80―89分的12人,...
    逸or藝閱讀 8,554評論 0 0
  • 轉自原文地址 前幾天看了《Code Review 程序員的寄望與哀傷》,想到我們團隊開展Code Review也有...
    bruce_wu閱讀 2,190評論 1 13