最短路历来是令各路OIer害怕的东西
那
本蒟蒻就分享一下我的Dijsktra+Heap优化
例题&模板题
嗯
这里我的Dij是过了两题,大概是比SPFA快一点(不知道为啥SPFA在标准版下被卡飞)
进入正题
大家都知道dij每次找最小的点更新,而正常我们是线性扫一遍求最小,因此时间复杂度是
O ( n 2 ) O(n^2) O(n2) 于是我们发现线性扫一遍求最小
这些字很刺眼,于是我们想到了
我们只要维护一个小根堆就可以把线性扫的时间缩小到为 O ( ( m + n ) l o g n ) O((m+n)log n) O((m+n)logn)
当然,我们也可以用斐波那契堆 把时间压成 O ( m + n l o g n ) O(m+n logn) O(m+nlogn)
据wikipedia说dij+斐波那契堆是目前最快的最短路算法
然而1.本蒟蒻不会2.编程中用斐波那契堆优化常常会由于算法常数过大而导致速度没有显著提高
div--------------------------
这里本蒟蒻懒得打手动堆,于是我们就用C++中的优先队列
头文件
#include
定义
priority_queue,cmp> Q;
因为优先队列默认是“大根堆”
所以我们要手动该顺序
在定义全局变量时应该插入如下代码
struct cmp
{
bool operator()(int a,int b)
{
return dis[a]>dis[b];
}
};
然后简单介绍一下优先队列的基本操作
Q.push(int)
过程,将变量加入堆
int sth.=Q.top()
函数,堆顶元素
Q.pop()
过程,删掉堆顶
Q.empty()
bool函数,堆是否为空
好了
数据结构基本操作就到这里
下面是具体堆优化操作
结束了,和普通dij没啥区别
和原版一样
更新dis[i]时顺便记录path[i]表示从path[i]号点转移到i号(前驱),和前向星差不多
本人强迫症,用前向星存图,见谅
#include
#include
#include
#include
#include
#define INF 2147483647
using namespace std;
int n,m,cnt=0,start,end,dis[110000],vis[110000],b[110000],path[110000],print[110000];
struct map
{
int to,val,last;
}a[550000];
struct cmp
{
bool operator()(int a,int b)
{
return dis[a]>dis[b];
}
};
inline int read()
{
int x=0,f=0; char c=getchar();
while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f ? -x:x;
}
void add(int fr,int tow,int len)
{
a[++cnt]=(map){tow,len,b[fr]};b[fr]=cnt;
}
void dij(int start)
{
priority_queue,cmp> Q;
for(int i=0;i<=n;i++)dis[i]=INF;
memset(vis,0,sizeof(vis));
dis[start]=0;
Q.push(start);
int now,got;
while(!Q.empty())
{
now=Q.top();
Q.pop();
vis[now]=0;
for(int i=b[now];i>0;i=a[i].last)
{
got=a[i].to;
if(dis[got]==INF || dis[got]>dis[now]+a[i].val)
{
dis[got]=dis[now]+a[i].val;
path[got]=now;
if(!vis[got])
{
vis[got]=1;
Q.push(got);
}
}
}
}
}
int main()
{
n=read();m=read();start=read();end=read();
for(int i=1;i<=m;++i)
{
int x,y,len;
x=read(),y=read(),len=read();
add(x,y,len);
}
dij(start);
cnt=0;
for(int i=path[end];i;i=path[i])print[++cnt]=i;
for(int i=cnt;i>=1;--i)printf("%d ",print[i]);
return 0;
}