图论天花板:Dijkstra最短路径算法详解

一、上期回顾 Day30

掌握图论基础、邻接表、拓扑排序 ,解决任务依赖、有向图判环、课程排序问题。今天学习图论天花板级高频考点Dijkstra 单源最短路径算法


二、Dijkstra 算法核心概念

1. 解决什么问题

给定带权有向 / 无向图 ,求一个起点其他所有点最短路径

  • 权值:距离、时间、花费
  • 适用:边权非负(没有负数权值)

2. 核心思想(贪心)

  1. 每次选离起点最近未访问的点
  2. 用这个点松弛(更新)它邻居的距离
  3. 标记已访问,不再重复处理
  4. 直到所有点处理完毕

三、必备数据结构

  1. 邻接表 :存图(比邻接矩阵高效)

    复制代码
    vector<pair<int, int>> edge[N];
    // edge[u] = {v, w}  从u到v,边权w
  2. 距离数组 dist \[\]dist[i] 起点到 i 点的最短距离

  3. 访问数组 vis \[\]:标记已确定最短路径的点

  4. 优先队列(堆):堆优化,O (E log V),效率爆炸


四、堆优化 Dijkstra 万能模板(必背)

复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

const int N = 10005;
vector<pair<int, int>> edge[N];  // 邻接表:to, weight
int dist[N];                     // 最短距离
bool vis[N];                     // 访问标记
int n, m;                        // 点数,边数

// Dijkstra 堆优化版
void dijkstra(int start)
{
    // 初始化距离为无穷大
    fill(dist, dist + N, INT_MAX);
    fill(vis, vis + N, false);
    dist[start] = 0;

    // 优先队列:小根堆(距离最小优先)
    // pair<int, int>:{距离,节点编号}
    priority_queue<pair<int, int>,
                   vector<pair<int, int>>,
                   greater<pair<int, int>>> pq;

    pq.push({0, start});

    while (!pq.empty())
    {
        auto [d, u] = pq.top();
        pq.pop();

        if (vis[u]) continue;   // 已处理跳过
        vis[u] = true;

        // 遍历所有邻居
        for (auto [v, w] : edge[u])
        {
            if (!vis[v] && dist[v] > d + w)
            {
                dist[v] = d + w;
                pq.push({dist[v], v});
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        edge[u].emplace_back(v, w);
        // 无向图再加一行 edge[v].emplace_back(u, w);
    }

    dijkstra(1);  // 从1号点出发

    // 输出到所有点的最短距离
    for (int i = 1; i <= n; i++)
        cout << dist[i] << " ";

    return 0;
}

五、关键步骤拆解

  1. 初始化:起点距离 = 0,其余无穷大

  2. 小根堆 :每次拿最近点

  3. 松弛操作

    复制代码
    if (dist[v] > dist[u] + w)
        dist[v] = dist[u] + w;
  4. 标记访问:每个点只处理一次,保证效率


六、适用场景

  1. 地图导航最短路径
  2. 网络传输最小延迟
  3. 工程最小花费
  4. 带权图单源最短路(无负权

七、易错点提醒

  1. 必须用小根堆(greater),不能用默认大根堆
  2. 边权不能为负数,否则失效
  3. 无向图 = 双向加边
  4. 距离数组初始化为极大值

八、今日核心总结

  1. Dijkstra = 贪心 + 堆优化 + 松弛操作
  2. 解决带权图单源最短路径
  3. 邻接表存图,小根堆提速
  4. 时间复杂度 O(E log V),刷题首选
  5. 边权不能为负

九、课后练习

  1. 手写堆优化 Dijkstra 模板
  2. 构造简单带权图,求起点到各点最短路
  3. 尝试无向图写法
相关推荐
Jerry20 分钟前
LeetCode 454. 四数相加 II
算法
可编程芯片开发1 小时前
基于CPS-SPWM链式STATCOM系统在电压不平衡环境下控制策略的simulink建模与仿真
算法
Jerry1 小时前
LeetCode 202. 快乐数
算法
hans汉斯2 小时前
基于改进交叉熵损失函数与Transformer的心电信号高风险分类研究
功能测试·深度学习·算法·yolo·目标检测·分类·transformer
Jerry2 小时前
LeetCode 349. 两个数组的交集
算法
fpcc3 小时前
数据结构—表
数据结构
YuK.W3 小时前
Leetcode100: 70.爬楼梯、118.杨辉三角、198.打家劫舍
java·算法·leetcode
随意起个昵称3 小时前
状压dp-基础题目2([USACO12MAR] Cows in a Skyscraper G)
c++·算法·动态规划
Funing74 小时前
FreeRTOS学习day1:Keil 工程配置与 FreeRTOS 链表机制理解
数据结构·学习·链表
Jerry4 小时前
LeetCode 1002. 查找共用字符
算法