Dijkstra 算法

Dijkstra 算法

后续可能会有更新……

一、算法文字说明(笔记整理)

普通堆实现的 Dijkstra 算法,时间复杂度 O(m * log m),m 为边数。

  1. distance[i] 表示从源点到 i 点的最短距离,visited[i] 表示 i 节点是否从小根堆弹出过。
  2. 准备好小根堆,小根堆存放记录:(x点, 源点到x的距离),小根堆根据距离组织。
  3. 令 distance[源点] = 0,(源点, 0) 进入小根堆。
  4. 从小根堆弹出 (u点, 源点到u的距离):
    • a. 如果 visited[u] == true,不做任何处理,重复步骤 4;
    • b. 如果 visited[u] == false,令 visited[u] = true,u 就算弹出过了;
      • 然后考察 u 的每一条边,假设某边去往 v,边权为 w:
          1. 如果 visited[v] == false 并且 distance[u] + w < distance[v]:
            令 distance[v] = distance[u] + w,把 (v, distance[u] + w) 加入小根堆;
          1. 处理完 u 的每一条边之后,重复步骤 4;
  5. 小根堆为空过程结束,distance 表记录了源点到每个节点的最短距离。

二、对应代码实现

结合上述步骤,对应的一份极简、清晰的 C++ 模板代码如下:

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

const int N = 105; // 视题目节点数范围而定
vector<vector<pair<int, int>>> a(N);
const int INF = 0x3f3f3f3f;

int main()
{
    int n, m, s;
    cin >> n >> m >> s;
    for (int i = 1; i <= m; i ++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        a[u].push_back({v, w});
    }
    
    vector<int> dist(n + 1, INF);
    vector<int> vis(n + 1, 0);
    
    // 小根堆:存放 (源点到x的距离, x点)
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    
    // 3. 令 distance[源点] = 0,(源点, 0) 进入小根堆
    dist[s] = 0;
    pq.push({0, s});
    
    // 4. 从小根堆弹出
    while (!pq.empty())
    {
        auto [w, u] = pq.top();
        pq.pop();
        
        // 4a. 如果 visited[u] == true,不做任何处理
        if (vis[u]) continue;
        
        // 4b. 如果 visited[u] == false,令 visited[u] = true
        vis[u] = 1;
        
        // 考察 u 的每一条边
        for (auto it : a[u])
        {
            int v = it.first;
            int weight = it.second;
            
            // 1) 如果 visited[v] == false 并且 distance[u] + w < distance[v]
            if (dist[u] + weight < dist[v])
            {
                // 令 distance[v] = distance[u] + w,把 (v, distance[u] + w) 加入小根堆
                dist[v] = dist[u] + weight;
                pq.push({dist[v], v});
            }
        }
    }
    int res = 0;
    for (int i = 1; i <= n; i ++)
    {
        if (dist[i] == INF)
        {
            res = -1; // 如果有不可达节点
            break;
        }
        res = max(dist[i], res); // 这一部分是特定题目要求:求最远的最短路
    }
    cout << res << endl;
    
    return 0;
}
posted @ 2026-10-27 11:36  leaderling  阅读(7)  评论(0)    收藏  举报