朴素Dijkstra和堆优化版Dijkstra
总体思路
- 将所有的顶点分为两个部分:已知最短距离的顶点集合P和未知最短距离的顶点集合Q。最开始的时候,已知最短距离的顶点集合中只有源点。
- 初始化distance数组,将源点s到自己的距离设置为0,到其他顶点的距离姑且设置为Infinity。
- 依据distance数组,在未知顶点集合Q中选出距离源点最近的一个顶点u,放入P中,并考察所有以u为起点的边,以u作为中转点,检验是否能够减短源点到其他点的距离。如果有,就更新distance数组。这一步又叫松弛(relaxation)操作。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GzrWFXRR-1591143789255)(../../../图库/1590243662585.png)]](https://img-blog.csdnimg.cn/2020060308232044.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MzU2ODQw,size_16,color_FFFFFF,t_70)
朴素Dijkstra
- 时间复杂是 O(n^2+m), n 表示点数,m 表示边数
- 每一次外层循环都找到一个最小路径。
思路
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBXfEZYp-1591143789257)(../../../../../../%E5%9D%9A%E6%9E%9C%E5%90%8C%E6%AD%A5%E6%96%87%E4%BB%B6%E5%A4%B9/%E6%88%91%E7%9A%84%E5%9D%9A%E6%9E%9C%E4%BA%91/%E7%AE%97%E6%B3%95/%E5%9B%BE%E5%BA%93/1590242798361.png)]](https://img-blog.csdnimg.cn/20200603082329846.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MzU2ODQw,size_16,color_FFFFFF,t_70)
模板
int g[N][N];
int dist[N];
bool st[N];
int dijkstra()
{
memset(g, 0x3f, sizeof g);
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < n-1; i++)
{
int t = -1;
for (int j = 1; i <= n; j++)
if (!st[j] && (t == -1 || dist[j] < dist[t]))
t = j;
st[t] = true;
for (int j = 1; j <= n; j++)
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
堆优化Dijkstra
思路
- 堆维护所有点到起点的距离。
- 利用堆来代替(且找到离源点最小的点的序号)这一步。
- 时间复杂度是 O(mlogn)
- 我们可以将所有修改过的点直接插入堆中,堆中会有重复元素,但堆中元素总数不会大于 m。
typedef pair<int, int> PII;
int n;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 1});
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}