【模板】Dijkstra的heap优化

时间:2023-03-08 20:32:04

为了将最小费用最大流的spfa优化,决定将spfa换成heap优化的Dijkstra。(dijkstra不能处理负边权)

所以还得现学。。。

白点表示已经确定最短路径的点。

蓝点表示还未确定最短路径的点。

因为普通的dijkstra是每次从蓝点中找到一个距离起点的距离最小的点,然后把这个点变成白点,随后枚举这个点相连的所有蓝点,若以此白点为中转点到达相连蓝点的路径更短的话就更新蓝点到起点的最短距离。

这个时间复杂度是O(n^2)的。

显然,枚举在枚举到起点最小距离的蓝点时,可以运用heap优化。

所以时间复杂度就降为O((n+m)logn)。(n为顶点数,m为边数)

大部分情况下还是跑不过spfa的,慎用。

stl大法好。

——附带码

 #include <cstdio>
#include <queue>
#include <cstring>
#define Heap pair<int, int>
//第一个int存的是到起点的距离,第二个int存的是点的编号 using namespace std; const int INF = ;
int n, m, t, cnt;
int next[], to[], val[], head[], dis[];
bool vis[];
priority_queue <Heap, vector <Heap>, greater <Heap> > q;
//按照第一个int从小到大排序 inline void add(int a, int b, int c)
{
to[cnt] = b;
val[cnt] = c;
next[cnt] = head[a];
head[a] = cnt++;
} inline void Dijkstra(int s)//以s为起点
{
int i, u, v;
Heap x;
for(i = ; i <= n; i++) dis[i] = INF;
dis[s] = ;
q.push(make_pair(, s));//入队
while(!q.empty())
{
x = q.top();
q.pop();
u = x.second;
if(vis[u]) continue;//判断是否已经是最短路径上的点
vis[u] = ;
for(i = head[u]; i != -; i = next[i])//更新距离
{
v = to[i];
if(dis[v] > dis[u] + val[i])
{
dis[v] = dis[u] + val[i];
q.push(make_pair(dis[v], v));
}
}
}
} int main()
{
int i, j, a, b, c, s;
scanf("%d %d %d", &n, &m, &s);
memset(head, -, sizeof(head));
for(i = ; i <= m; i++)
{
scanf("%d %d %d", &a, &b, &c);
add(a, b, c);
}
Dijkstra(s);
for(i = ; i <= n; i++) printf("%d ", dis[i]);
return ;
}