Dijkstra的堆优化
先附上一个例题:P3371 【模板】单源最短路径
一眼扫去,最短路。。。
spfa可行,但是今天的主题是Dijkstra:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include<iostream> #include<algorithm> #include<cstdio> #define MAXN 10010 #define MAXM 500010 #define MAX 999999999 using namespace std; int n,m,s,c=1; int head[MAXN],path[MAXN]; bool vis[MAXN]; struct node{ int next,to,w; }a[MAXM<<1]; inline int read(){ int date=0,w=1; char c=0; while (c< '0' ||c> '9' ){ if (c== '-' )w=-1;c= getchar ();} while (c>= '0' &&c<= '9' ){date=date*10+c- '0' ;c= getchar ();} return date*w; } inline void add( int u, int v, int w){ a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++; } void dijkstra(){ for ( int i=1;i<=n;i++){path[i]=MAX;vis[i]= false ;} path[s]=0; for ( int i=1,k,v;i<=n;i++){ k=-1; for ( int j=1;j<=n;j++) if (!vis[j]&&(k==-1||path[k]>path[j]))k=j; if (k==-1) break ; vis[k]= true ; for ( int j=head[k];j;j=a[j].next){ v=a[j].to; if (!vis[v]&&path[v]>path[k]+a[j].w)path[v]=path[k]+a[j].w; } } for ( int i=1;i<=n;i++) printf ( "%d " ,path[i]==MAX?2147483647:path[i]); printf ( "\n" ); } int main(){ int u,v,w; n=read();m=read();s=read(); for ( int i=1;i<=m;i++){ u=read();v=read();w=read(); add(u,v,w); } dijkstra(); return 0; } |
然而,遇上某些题,n<=100,000,怎么办?
这时候,堆优化就出场了。
堆优化:
堆优化,即用堆来实现O( log2n )时间内找到到起点最短的未被松弛的点。
当然,你需要自定义结构体。
附代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #include<iostream> #include<algorithm> #include<cstdio> #include<queue> #define MAXN 10010 #define MAXM 500010 #define MAX 999999999 using namespace std; int n,m,s,c=1; int head[MAXN],path[MAXN]; bool vis[MAXN]; struct node{ int next,to,w; }a[MAXM]; struct Point{ int x,dis; bool operator <( const Point &p) const { return dis>p.dis; } }; inline int read(){ int date=0,w=1; char c=0; while (c< '0' ||c> '9' ){ if (c== '-' )w=-1;c= getchar ();} while (c>= '0' &&c<= '9' ){date=date*10+c- '0' ;c= getchar ();} return date*w; } inline void add( int u, int v, int w){ a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++; } void dijkstra(){ Point u,v; priority_queue<Point> q; for ( int i=1;i<=n;i++){path[i]=MAX;vis[i]= false ;} u.x=s;u.dis=path[s]=0; q.push(u); while (!q.empty()){ u=q.top(); q.pop(); if (!vis[u.x]){ vis[u.x]= true ; for ( int i=head[u.x];i;i=a[i].next){ v.x=a[i].to; if (!vis[v.x]){ path[v.x]=min(path[v.x],path[u.x]+a[i].w); v.dis=u.dis+a[i].w; q.push(v); } } } } for ( int i=1;i<=n;i++) printf ( "%d " ,path[i]==MAX?2147483647:path[i]); printf ( "\n" ); } int main(){ int u,v,w; n=read();m=read();s=read(); for ( int i=1;i<=m;i++){ u=read();v=read();w=read(); add(u,v,w); } dijkstra(); return 0; } |
不得不说,这玩意效率虽然没有spfa+SLF高,但是遇上了这题,你也是无可奈何地用它:
后记:
附上洛谷上的两次提交:(P3371)
朴素Dijkstra:Accepted 100
1036ms / 7.77MB
代码:1.11KB C++
Dijkstra+堆优化:Accepted 100
348ms / 9.49MB
代码:1.3KB C++
明显快了不少。
不过出题人没事干也不会卡你的spfa,至少在NOIP这种考试中。。。
分类:
图论——最短路
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络