Dijkstra算法解决单源最短路径
单源最短路径问题:给定一个带权有向图 G = (V, E), 其中每条边的权是一个实数.另外,还给定 V 中的一个顶点,称为源.现在要计算从源到其他所有各顶点的最短路径长度.这里的长度是指路上各边权之和.这个问题通常称为单源最短路径问题.
Dijkstra算法:
一:基本算法
将图 G 中所有的顶点 V 分成两个顶点集合 VA 和 VB.如果源点 S 到 u 的最短路径已经确定,则点 u 属于集合 VA ,否则属于集合 VB.最开始的时候 VA 只包含源点 S,其余的点属于 VB,算法结束时所有由源点 S 可达的点属于 VA ,由源点 S 不可达的点仍留在 VB 中.可以在求出最短路径长的同时记录最短路径,方法是距离终点的前一个点,这样只要倒着往回查就能确定整条最短路径.算法的适用范围是权值非负的图,即解决带有非负权值的图中的单源最短路径问题.
二:具体步骤
(1):首先初始化,将源点 S 到图中各点的直接距离当做初始值记录为 S 到各点的最短距离,如果不能直接到达,记为 INF, S 到 S 的距离为 0.
(2):在所有属于 VB 的点中找一个 S 到其路径长度最短的点 u, 将 u 从VB 中除去,加入到 VA 中,即当前求出的从 S 到 u 的路径为 S 到 u 的最短路径.
(3):由新确定的 u 点更新 S 到 VB 中每一点 v 的距离, 如果 S 到 u 的距离加上 u 到 v 的直接距离小于当前 S 到 v 的距离,表明新生成的最短路径的长度要比前面计算的更短,那么就更新这个距离,同时更新最短路径.
(4):重复(2),(3)步骤,直到VB 中已经没有剩余的点或者VB 中的点都不能由源点 S 到达为止.
三:伪代码
在这里, s 代表源, setA[] 记录点属于哪个集合: true 表示属于VA , false 表示属于VB ; map[][] 记录图的信息, map[u][v]为点 u 到点 v 的边的长度, 结果保存在 dist[]中,pre[]记录最短路径终点的前趋.
(1):初始化:源的距离 dist[s] 设为0,其他的点距离设为 map[s][i],即 dist[i] = map[s][i].setA[s]设为 true,其他各点的p[i] = false.
(2):循环 n - 1次:
a:在 VB 中的点中取一 s 到其距离最小的点 k, setA[k] = true. 如果所有的 k 都不可达,退出循环,算法结束.
b:对于每个与 k 相邻且在 VB 中的点 j,更新 s 到 j 的最短路径. 如果 dist[k] + map[k][j] < dist[j], 那么 dist[j] = dist[k] + map[k][j], 此时到点 j 的最短路径上, 终点 j 的前一个节点即为 k, 即 pre[j] = k.
四:以图为例
初始化图:

初始化数组:
dist 1 2 3 4 5 6
0 INF 10 INF 30 100
setA 1 2 3 4 5 6
1 0 0 0 0 0
第一步:
从 dist 数组中选择属于集合 B 且与 点“1” 距离最短的点,显然是点 “3”, 把点 “3” 加入集合 A.则改变后的图为:

然后选择与点 “3” 相邻的点且属于集合 B 的点,只有点 4,选择之后更新:
dist[4](INF) < dist[3](10) + map[3][4](50) 显然这里是成立的, 则dist[4] = dist[3] + map[3][4] = 60,更新后的数组为:
dist 1 2 3 4 5 6
0 INF 10 60 30 100
setA 1 2 3 4 5 6
1 0 1 0 0 0
第二步:
再次从 dist 数组中选择属于集合 B 且距离 源点 “1” 最短的点,可以看出这次拓展的点是点 “5”,把点 “5”加入集合A,图变为:

选择与点 “5” 相邻的点且属于集合 B 的点,这里有点 “4” 和点 “6”.则做比较更新:
点“4”: dist[4](60) < dist[5](30) + map[5][4](20) 这里是成立的,则dist[4] = dist[5](30) + map[5][4](20) = 50;
点“6”: dist[6] < dist[5](30) + map[5][6](60) 这也是成立的,则 dist[6] = dist[5] + map[5][6] = 90;
更新数组得:
dist 1 2 3 4 5 6
0 INF 10 50 30 90
setA 1 2 3 4 5 6
1 0 1 0 1 0
第三步:
再次选择符合条件的点,可知下一个待扩展点为点 “4”.

同样选择与点“4”相邻且属于集合B的点,可选点为 点 “6”.对点 “6”做更新:
dist[6](90) < dist[4](50) + map[4][6](10) 这里也是成立的,那么dist[6] = dist[4] + map[4][6] = 60. 更新后的数组为.
dist 1 2 3 4 5 6
0 INF 10 50 30 60
setA 1 2 3 4 5 6
1 0 1 1 1 0
第四步:
继续再集合B中选择距离源点最短的点,可得点 “6”.

由于此时已经没有和点 “6”相邻,且属于集合B的点了.那么把点 “6” 加入集合A继续下一步.
dist 1 2 3 4 5 6
0 INF 10 50 30 60
setA 1 2 3 4 5 6
1 0 1 1 1 1
第五步:
此时满足距离源点最短且属于集合B的点不存在,即剩下的属于集合B的点,已不可到达那么此时算法结束:

算法结束后,dist数组里保存的就是图中每点到源点的最短距离:
dist 1 2 3 4 5 6
0 INF 10 50 30 60
其中点 “2”为 不可到达.
五:代码
const int INF = INT_MAX;
const int MAXN =;
int mmap[MAXN + ][MAXN + ];//记录图的信息
int dist[MAXN + ];//dist[i]表示点 i 到源点的最短距离
int pre[MAXN + ];//记录前趋 记录最短路径
bool setA[MAXN + ];//是否属于集合A,集合A代表着已经确定最短路径的点集 void Dijkstra(int n, int s) {// s 为源点
for(int i = ; i <= n; i++) { //初始化
setA[i] = false;
if(i != s) {
dist[i] = mmap[s][i];
pre[i] = s;
}
}
dist[s] = , setA[s] = true;
for(int i = ; i <= n - ; i++) {//求 s 到其他 n - 1个节点的最短路径
int minn = INF;
int k = ;
for(int j = ; j <= n; j++) { // 在属于集合 Vb 的点中取一点, 满足 s 到其的距离最小
if(!setA[j] && dist[j] < minn) {
minn = dist[j], k = j;
}
}
if(!k) return; // 没有点可以扩展,即剩余的点不可达,则结束算法
setA[k] = true; //将新找的点从集合 Vb 中除去, 加入集合 Va
for(int j = ; j <= n; j++) {
//对于每个与 k 相邻 且属于 Vb 的点,更新 s 到 j 的最短路径
if(!setA[j] && mmap[k][j] != INF && dist[j] > dist[k] + mmap[k][j]) {
dist[j] = dist[k] + mmap[k][j];
pre[j] = k;
}
}
}
}
参考文献:<<图论及应用>> <<数据结构>>
Dijkstra算法解决单源最短路径的更多相关文章
- Dijkstra算法详细(单源最短路径算法)
介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...
- Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 32824 Accepted: 11098 Description Bes ...
- 【转】Dijkstra算法(单源最短路径)
原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...
- 【算法】Dijkstra算法(单源最短路径问题)(路径还原) 邻接矩阵和邻接表实现
Dijkstra算法可使用的前提:不存在负圈. 负圈:负圈又称负环,就是说一个全部由负权的边组成的环,这样的话不存在最短路,因为每在环中转一圈路径总长就会边小. 算法描述: 1.找到最短距离已确定的顶 ...
- Dijkstra算法求单源最短路径
Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店 ...
- dijkstra算法解决单源最短路问题
简介 最近这段时间刚好做了最短路问题的算法报告,因此对dijkstra算法也有了更深的理解,下面和大家分享一下我的学习过程. 前言 呃呃呃,听起来也没那么难,其实,真的没那么难,只要弄清楚思路就很容易 ...
- SPFA算法与dijkstra算法求单源最短路径的比较
SPFA是运用队列,把所有的点遍历到没有能更新的,点可以重复入队 如题http://www.cnblogs.com/Annetree/p/5682306.html dijkstra是每次找出离源点最近 ...
- 【算法】单源最短路径和任意两点最短路径总结(补增:SPFA)
[Bellman-Ford算法] [算法]Bellman-Ford算法(单源最短路径问题)(判断负圈) 结构: #define MAX_V 10000 #define MAX_E 50000 int ...
- 51nod 1445 变色DNA ( Bellman-Ford算法求单源最短路径)
1445 变色DNA 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一只特别的狼,它在每个夜晚会进行变色,研究发现它可以变成N种颜色之一,将这些颜色标号为0,1 ...
随机推荐
- hdu 3486 Interviewe (RMQ+二分)
Interviewe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- hdu 6057 Kanade's convolution(子集卷积)
题解: 然后就是接下来如何fwt 也就是如何处理bit(x) - bit(y) = bit(k)这个条件. 其实就是子集卷积. 把bit(x)和bit(y)划分成两个集合,然后就是子集卷积的形式. 这 ...
- AtCoder Code Festival 2017 Team Relay J - Indifferent
题目大意:共$2n$个价格$p_i$.两人轮流取.你每次取最大的,对方每次随机取.问你取的期望和是多少. 题解:从小到大排序,$\sum\limits_{i=0}^{2n-1} \frac{i*p_i ...
- 2018牛客多校第三场 C.Shuffle Cards
题意: 给出一段序列,每次将从第p个数开始的s个数移到最前面.求最终的序列是什么. 题解: Splay翻转模板题.存下板子. #include <bits/stdc++.h> using ...
- MFC 对话框透明效果
网上找的资料自己改了改,在这里记录和分享一下,主要是TransparentWnd函数. 在子类的OnShowWindow函数中调用 ShowWindowAlpha() #pragma once tem ...
- 前端面试:什么是css reset
HTML标签在浏览器中都有默认的样式,不同的浏览器的默认样式之间存在差别.例如ul默认带有缩进样式,在IE下,它的缩进是由margin实现的,而在Firefox下却是由padding实现的.开发时浏览 ...
- 在eclipse中使用JUnit4,以及使用JUnit4进行单元测试的技巧
一 在eclipse中使用JUnit4 首先在工程上右键,选择属性,找到Java Builder Path,添加JUnit4的lib,如下图: 在要测试的类上右键新建 Junit test cas ...
- 【BZOJ】ARC083 E - Bichrome Tree
[算法]树型DP [题意]给定含n个点的树的形态,和n个数字Xv,要求给每个点赋予黑色或白色和权值,满足对于每个点v,子树v中和v同色的点的权值和等于Xv.n<=10^5 [题解]首先每个点的权 ...
- NOIP2016提高组D1T2 天天爱跑步
n<=300000个点的树,每个点有个人于第Ti秒观测,有m<=300000个人于时间0开始从Sj跑到Tj,速度1个点每秒,输出每个点上的人观察到的跑步的人的数量. 前25分:直接模拟每条 ...
- 标签 JLable 类
标签JLable上可以添加图像,当鼠标停留在标签上时,可以显示一段提示文字. package first; import javax.swing.*; import java.awt.*; impor ...