当前位置: 首页 > news >正文

Dijkstra算法求图上单源最短路

Dijkstra算法是一种求解非负权图单源最短路的算法。

如果图中有负权边,Dijkstra算法不能得到正确的答案。

记源点为 \(s\) 点、\(i\) 点到 \(s\) 点的最短路为 \(dis(i)\),已确定最短路长度的点集为 \(S\),未确定最短路长度的点集 \(T\)。则算法步骤如下:

  1. \(s\) 点属于 \(S\) 集合,其它点都属于 \(T\) 集合。记\(dis(s)=0\),其他点 \(dis = +\infty\)
  2. \(T\) 集合中 \(dis\) 最小的一个点 \(p\),移到 \(S\) 集合中。对 \(p\) 点的所有出边执行如下操作:
    记那条出边的长(权值)为 \(w\)、边另一端的点为 \(q\) 点。若 \(dis(p) + w < dis(q)\),那么 \(dis(q) = dis(p) + w\)
  3. \(T\) 集合不为空,再次进行步骤2。

朴素实现在步骤2选点时,直接暴力遍历在 \(T\) 集合寻找最短路长度最小的结点。这样寻找极慢。用优先队列优化是容易写的优化方法,做法是:队列按 \(dis\) 值排队,大者优先;更新 \(dis(i)\)\(i\) 点入队;出队 \(i\) 点时若 \(i\) 点是已在 \(S\) 集合中则跳过。

如下是用优先队列优化的Dijkstra算法。

点击查看代码
#include <vector>
#include <queue>// 相当于正无限
const unsigned int LARGE_NUMBER = 0x3f3f3f3f;// 边的结构体
struct side {unsigned int to_point, length;side(unsigned int to_point, unsigned int length) {this->to_point = to_point;this->length   = length;}
};// 用于优先队列
struct updated_point {unsigned int point_id, answer;updated_point(unsigned int point_id, unsigned int answer) {this->point_id = point_id;this->answer   = answer;}// 从大到小排列bool operator<(const updated_point& right) const {return this->answer > right.answer;}
};/*
point_num:   点数。
start_point: 源点编号。
sides:       边数组。sides[i]内存放编号i的点的所有边。
answers:     答案数组。
*/
void dijkstra(unsigned int point_num, unsigned int start_point, std::vector<side>* sides, unsigned int* answers) {bool* is_visited = new bool[point_num];std::priority_queue<updated_point> updated_points;// 初始化for (unsigned int i = 0; i < point_num; ++i) {answers[i] = LARGE_NUMBER;is_visited[i] = false;}answers[start_point] = 0;updated_points.push(updated_point(start_point, 0));while (!updated_points.empty()) {updated_point point = updated_points.top();updated_points.pop();// 确认不在S集合中if (is_visited[point.point_id]) {continue;}// 放入S集合is_visited[point.point_id] = true;// 遍历边for (unsigned int i = 0; i < sides[point.point_id].size(); ++i) {side out_side = sides[point.point_id][i];// 更新disif (answers[out_side.to_point] > answers[point.point_id] + out_side.length) {answers[out_side.to_point] = answers[point.point_id] + out_side.length;updated_points.push(updated_point(out_side.to_point, answers[out_side.to_point]));}}}// 清理delete[] is_visited;
}

练习题:
洛谷 P4779 【模板】单源最短路径(标准版)

http://www.westin-hotel.cn/news/431.html

相关文章:

  • 软工7.25
  • NOIP 二十年 DP 训练总结
  • POLIR-Laws-电商法(电子商务法): 电子商务法视角下平台服务协议的合规探讨
  • React 错误边界详解
  • 7 月 25 日模拟赛 - sb
  • 第六篇:Docker Compose
  • 练习cf1916A. 2023
  • 编程研发工作日记
  • 好好
  • 一种比较简洁的线段树写法(未完待续)
  • 暑假7.25
  • 手把手教你用Qwen Code快速集成ModelGate——省心调用AI大模型!
  • 30天总结-第二十五天
  • 虚拟机镜像源配置
  • 用户权限基础
  • P12547 [UOI 2025] Simple Subsequence 题解
  • 2025.7.25打卡
  • 高精度采样系统设计及应用
  • 深度优先搜索算法:回溯算法
  • 7 月 22 日模拟赛 - sb
  • 2025.7.25随笔
  • 基于Java的在线家政预约网站系统源码+远程运行(springboot+vue开发)
  • 2025.7.25学习日记
  • 周期思维:思考事物运行方式的一把好“钥匙”
  • AWS Amplify Swift 库 - 强大的iOS/macOS/watchOS/tvOS开发工具
  • 2025 贵阳 代码源 Day 2
  • 2025 贵阳 代码源 Day 5 模拟赛
  • 计数中的统计方法 - ET
  • DP of DP - ET
  • 计数中的容斥 - ET
  • 微网站分享功能吉林百度查关键词排名
  • 做物理的网站潍坊网站建设公司
  • php在网站上怎么做充值智能建站平台