题目描述
利用堆优化Dijkstra求最短路 II
和朴素的思路差不多,原来是循环n-1次,每次更新t(不在st集合中并且距离最短),更新st集合(插入t),和节点i最短距离dist[i]。
利用堆优化后,直接取堆顶元素(距离最短),这个元素相当于t。用邻接标存储t的临界点和这两个点的距离。
样例
3 3
1 2 2
2 3 1
1 3 4
算法1
(堆优化) $O(mlogn)$
时间复杂度
参考文献
C++ 代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 200010;
int e[N], ne[N], h[N], w[N], idx;
int dist[N], n;
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b; ne[idx] = h[a]; w[idx] = c; h[a] = idx++;
}
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
/*构建小根堆,每次取得距离点1最小的点*/
priority_queue<PII, vector<PII>, greater<PII>> heap;
/*插入第一个点1*/
heap.push({0,1});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second;
/*更新t为不在集合st的到点1最小的点*/
if(st[ver])continue;
/*放入集合st*/
st[ver] = true;
/*使用邻接表更新其他点的dist*/
for(int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
/*注意是w[i]不是w[j], i代表着点ver的邻接表的点的位置*/
if(dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
/*每次都是在堆里取t,更新了其他点之后都要重新插入更新的点*/
heap.push({dist[j], j});
// cout << j << " " << dist[j] << endl;
}
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
memset(h, -1, sizeof h);
int a, b,c;
int m; cin >> n >> m;
while(m--)
{
cin >> a >> b >> c;
add(a, b, c);
}
cout << dijkstra() << endl;
return 0;
}