dijkstra算法的堆优化版本,把找dist数组中的最小值的复杂度优化为O(1).
#include<iostream>
#include<cstring>
using namespace std;
const int N = 150010;
int heap[N], heap_node[N], ss = 1;
int dist[N];
int h[N], e[N], w[N], ne[N], idx;
int st[N];
int n, m;
void heap_swap(int a, int b){
swap(heap[a], heap[b]);
swap(heap_node[a], heap_node[b]);
}
void up(int x){
while(x / 2 && heap[x] < heap[x / 2]){
heap_swap(x, x / 2);
x /= 2;
}
}
void down(int x){
int t = x;
if(x * 2 <= ss && heap[x * 2] < heap[t]) t = x * 2;
if(x * 2 + 1 <= ss && heap[x * 2 + 1] < heap[t]) t = x * 2 + 1;
if(t != x){
heap_swap(x, t);
down(t);
}
}
int dijkstra(){
dist[1] = 0;
heap_node[ss] = 1;
heap[ss] = 0;
while(ss){
int k = heap_node[1];
heap_swap(1, ss --);
down(1);
if(st[k]) continue; // 注意同一个结点可能在堆中存在多个不同距离的记录,所以此处用st来保证时间复杂度,这里不写这个判断也是对的,但是无法保证时间复杂度
st[k] = 1;
for(int i = h[k]; ~ i; i = ne[i]){
int j = e[i];
if(dist[j] > dist[k] + w[i]){
dist[j] = dist[k] + w[i];
++ ss;
heap_node[ss] = j;
heap[ss] = dist[j];
up(ss);
}
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
void add(int a, int b, int x){
e[idx] = b, w[idx] = x, ne[idx] = h[a], h[a] = idx ++;
}
int main(){
memset(h, -1, sizeof h);
memset(dist, 0x3f, sizeof dist);
cin >> n >> m;
while(m --){
int a, b, w;
cin >> a >> b >> w;
add(a, b, w);
}
cout << dijkstra() << endl;
return 0;
}