单源最短路 Dijkstra 学习笔记
算法实现
Dijkstra是通过贪心来进行实现的。所以不能判定有负边的图。
看一下这张图,我们从号点开始遍历,且令为第个点到好点的最短路径。
首先我们把已知最短路的点设为长方形,未知的设为圆形即可,那么一号点就是已知的,及。
接下来,从已知点集到未知点集最短的一个点为点,及。
然后一步一步推,如图:
然后是号点最近
再就是号点。
这样就可以推下去就可以了。
注意:最短的那个点并不是指边权,比如说号点,它的值是由,不仅仅是。
代码实现
#include<cstdio>//采用Dijstra #include<vector>//朴素 #include<cstring>//使用vector动态数组存储 #define maxn 500039 using namespace std; int ans[maxn]; int n,m,s,i,j,from; struct Di{ int to,q; }f; vector<Di> q[maxn]; int v[maxn]; int T,minx,a,b; int main(){ scanf("%d%d%d",&n,&m,&s); memset(ans,0x3f,sizeof(ans)); ans[s]=0; for(i=1;i<=m;i++){ scanf("%d%d%d",&from,&f.to,&f.q); q[from].push_back(f); } v[s]=1; for(int k=1;k<n;k++){//核心 Dijstra minx=0x7fffffff; for(i=1;i<=n;i++) if(v[i]) for(j=0;j<q[i].size();j++) if(ans[i]+q[i][j].q < minx && !v[q[i][j].to] ){ minx=ans[i]+q[i][j].q; a=q[i][j].to; } v[a]=1; ans[a]=minx; } for(int i=1;i<=n;i++) if(ans[i]==0x3f3f3f3f) printf("2147483647 "); else printf("%d ",ans[i]); return 0; }
堆优化-Update 20201106
这里会发现,我们这里有三层循环,大大降低了效率,所以我们需要使用堆来进行优化。
我们看一下Dijkstra的步骤:
- 设置起点
- 从已知未知集中找到最短的一条路径
- 更新这个点的最短路
- 重复24
我们发现第2步可以进行优化。
怎么优化呢?
我会zkw非递归式线段树!
我会斐波那契额堆!
我会堆!
我们把所有从已知点集到扩展出的所有点扔近一个堆。当然, 最小的在堆顶部就可以了。
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100039 #define maxm 200039 using namespace std; //#define debug typedef int Type; inline Type read(){ Type sum=0; int flag=0; char c=getchar(); while((c<'0'||c>'9')&c!='-') c=getchar(); if(c=='-') c=getchar(),flag=1; while('0'<=c&&c<='9'){ sum=(sum<<1)+(sum<<3)+(c^48); c=getchar(); } if(flag) return -sum; return sum; } struct JTZ{ int num,dist; bool operator > (const JTZ x) const { return this->dist > x.dist; } }; priority_queue<JTZ,vector<JTZ>,greater<JTZ> > q; int dist[maxn],vis[maxn],n,m,s; int u,v,w; int head[maxn],nex[maxm],to[maxm],c[maxm],k; #define add(x,y,z) c[++k]=z;\ to[k]=y;\ nex[k]=head[x];\ head[x]=k; void Dij(){ q.push((JTZ){s,0}); dist[s]=0; while(!q.empty()){ int cur=q.top().num; q.pop(); if(vis[cur]) continue; vis[cur]=1; for(int i=head[cur];i;i=nex[i]) if(c[i]+dist[cur]<dist[to[i]]) if(!vis[to[i]]){ dist[to[i]]=c[i]+dist[cur]; q.push((JTZ){to[i],dist[to[i]]}); } } return; } int main(){ n=read(); m=read(); s=read(); for(int i=1;i<=m;i++){ u=read(); v=read(); w=read(); add(u,v,w); } memset(dist,0x7f,sizeof(dist)); Dij(); for(int i=1;i<=n;i++) printf("%d ",dist[i]); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具