Djikstra算法
Dijkstra算法:
Dijkstra算法常用于求无负权边中的最短路,
在优化后有比Bellman-Ford算法优秀很多的时间复杂度。
同样的,我们引入记号:
G = <V,E>代表一个简单有向图(简单图:没有重边和自环)
n = |V|代表顶点数
m = |E|代表边数
l(u,v)代表u到v的边权
S代表起点,T代表终点
dist(u)代表当前求出的S到u的最短路径长度
Dijkstra算法简介:
我们要维护一个顶点集合C,
满足对于所有集合C中的顶点x,我们都已经找到了起点S到x的最短路,
此时,dist(x)记录的就是最终最短路的长度。
Dijkstra算法流程:
1. 初始化:
将C设置为空,将S的距离设置为0,其余顶点的距离设置为正无穷。
2. 更新:
每一轮中,将离起点最近的(dist最小,不能是无穷大)还不在C中的顶点加入C,
并且用这个点连出去的边,通过松弛操作尝试更新其他点的dist。
3. 判断:
当T(如果T存在)或者没有新的点加入C时,算法结束。
由于图上并不存在负权边,可以证明每次加入C的点,
都已经找到了从起点到它的最短路。
代码实现:O(n2 + m)
1 const int N = 10000; 2 3 struct Node{ 4 int y, v; 5 Node(int _y, int _v){ 6 y = _y; 7 v = _v; 8 }; 9 }; 10 11 vector <Node> edge[N + 1]; 12 int n, m, dist[N + 1]; 13 bool b[N + 1]; 14 15 int Dijkstra(int s, int t){ 16 memset(b, false, sizeof(b)); 17 memset(dist, 127, sizeof(dist)); 18 dist[s] = 0; 19 while(1){ 20 int x = -1; 21 for (int i = 1;i <= n;i++){ 22 if (!b[i] && dist[i] < 1 << 30){ 23 if (x == -1 || dist[i] < dist[x]){ 24 x = i; 25 } 26 } 27 } 28 if (x == t || x == -1){ 29 break; 30 } 31 b[x] = true; 32 for (auto p : edge[x]){ 33 dist[p.y] = min(dist[p.y], dist[x] + p.v); 34 } 35 } 36 return dist[t]; 37 }
堆优化Dijkstra:O((n + m)log n)
1 //用一个堆来维护dist数组,可以使用set,也可以使用priority_queue 2 const int N = 10000; 3 4 struct Node{ 5 int y, v; 6 Node(int _y, int _v){ 7 y = _y; 8 v = _v; 9 }; 10 }; 11 12 set < pair<int, int>> q; 13 vector <Node> edge[N + 1]; 14 int n, m, dist[N + 1]; 15 16 int Dijkstra(int s, int t){ 17 memset(dist, 127, sizeof(dist)); 18 dist[s] = 0; 19 q.clear(); 20 21 for (int i = 1;i <= n;i++){ 22 q.insert(mp(dist[i], i)); 23 } 24 25 while(!q.empty()){ 26 int x = q.begin()->second; 27 q.erase(q.begin()); 28 if (x == t || dist[x] > 1 << 30){ 29 break; 30 } 31 for (auto p : edge[x]){ 32 if (dist[x] + p.v < dist[p.y]){ 33 q.erase(mp(dist[p.y], p.y)); 34 dist[p.y] = dist[x] + p.v; 35 q.insert(mp(dist[p.y], p.y)); 36 } 37 } 38 } 39 return dist[t]; 40 }
(未完待续......)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理