最短路径问题
有权图的单源最短路算法
Dijkstra 算法
给定任何一个非负权边的图
设已找到的最短路径的结点集合为
重复以下步骤:
- 从集合
中基于 中找到当前已知的最短路径结点 加入集合 中 - 基于
所相连的结点 更新 数组,即 - 重复1、2步骤直到所有结点都加入集合
证明
设算法迭代每一次加入集合
- 第一次加入的结点
显然是最短路径。 - 假设第K次加入的结点
为最短路径,此时集合S为 ,现证明根据算法运行第 k + 1次加入的结点 仍为最短路径。 - 反证,假设加入的
不是最短路径,即存在另外一条路径为最短路径,设 为该路径中不在集合 的第一个结点,则 ,dijkstra的算法的第一个步骤是每次从集合T中基于 选取距离最小的结点加入集合 ,因此 ,因此产生矛盾。得证。
路径一定是按照递增(非递减)的顺序生成,且经过收录后经过更新不会改变已收录的点最短路径
如果收录后将
每次从未收录的顶点中选一个dist最小的收录(必为最短路径)贪心
邻接表+优先队列 实现Dijkstra算法
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define INFINITY 10000
typedef int Vertex;
struct Edge {
int Adj; //邻接点
int Weight;
};
vector<vector<Edge>> G;
vector<int> dist;
vector<Vertex> path;
int Nv, Ne;
void buildGraph() {
cin >> Nv >> Ne;
G.resize(Nv + 1); //调整邻接表的大小为n
for (int i = 0; i < Ne; i++) {
int v1, v2, w; // v1和v2表示边的两个端点,w表示边的权重
cin >> v1 >> v2 >> w;
G[v1].push_back(Edge{ v2, w }); // 在v1的邻接表中添加一条边(v1, v2, w)
G[v2].push_back(Edge{ v1, w }); // 在v2的邻接表中添加一条边(v2, v1, w)
}
}
struct MyType {
Vertex index;
int dist;
friend bool operator < (const MyType& a, const MyType& b) {
return a.dist > b.dist; //重载小于号,变成最小堆
}
};
void dijkstra(Vertex cur) {
dist = vector<int>(Nv, INFINITY); //将dist初始化为正无穷,使得以后能够进行更新
path = vector<Vertex>(Nv, -1);
vector<bool>collected(Nv, false);
dist[cur] = 0;
priority_queue<MyType>H;
H.push({cur, dist[cur]});
while (!H.empty()) {
Vertex V = H.top().index;
H.pop();
collected[V] = true;
for (Vertex W = 0; W < G[V].size(); W++) {
Vertex next = G[V][W].Adj; //找到cur的邻接点
if (!collected[next]) { //如果当前点未被收录
if (dist[V] + G[V][W].Weight < dist[next]) { //且dist可以更新得更小
dist[next] = dist[V] + G[V][W].Weight;
path[next] = V;
H.push({ next,dist[next] });
}
}
}
}
}
注意:
Dijkstra算法不适用负权
Dijkstra算法核心思想是每次从未确定最短路径的顶点集合中选出距离源点最近的一个顶点,然后以该顶点为中介,更新其他顶点到源点的距离。
这个过程中,Dijkstra算法会维护一个不变量,即已确定最短路径的顶点集合中的任意顶点到源点的距离都是最短的,而未确定最短路径的顶点集合中的任意顶点到源点的距离都是不小于最短的。
如果图中存在负权边,那么负权边会破坏Dijkstra算法的不变量,使得已确定最短路径的顶点集合中的某些顶点到源点的距离不是最短的,而未确定最短路径的顶点集合中的某些顶点到源点的距离是最短的。这样就会导致Dijkstra算法选错中介顶点,从而得到错误的结果。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!