Dijkstra基本内容
dijkstra
众所周知,Dijkstra算法是一个十分有效且常用的算法。既然说了:
- 有效且常用
那我们就有学习的必要了呀!
话不多说,开始讲解。
概念
1.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。 Dijkstra 算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
2.Dijkstra 用来解决边权全为正的单源最短路问题, Dijkstra 算法又分为朴素 Dijkstra 算法和堆优化的 Dijkstra 算法。朴素版的 Dijkstra 算法的时间复杂度是
代码讲解
链式前向星
#define MOD 10000000007 #define INF 0x3f3f3f3f using namespace std; const int maxn=2000005; int n,m,s; int idx=1,e[maxn],w[maxn],head[maxn],ne[maxn]; int dis[maxn],vis[maxn];
MOD和INF不做过多解释,重点看e,w,head和ne数组。
void add(int a,int b,int c) { e[idx]=b; w[idx]=c; ne[idx]=head[a]; head[a]=idx++; }
这是一个简单的链式前向星,虽然有些奇怪的东西。
a是该点的位置,b是与该点相连的一点的位置,c则是边全
权。我们可以看到,e数组存储了一个点到另一个点的的终点,w存储了这两个点中边的边权,ne和head数组则是普通的链式前向星啦!
结构体
struct Node { int dis,x; bool operator<(Node p)const{return dis>p.dis;} Node(int dis,int x):dis(dis),x(x){} };
我们使用重载运算符 主要是装。
Dijkstra 主体
void dijstra() { memset(dis,INF,sizeof(dis)); priority_queue<Node>q; dis[s]=0; Node u(dis[s],s); q.push(u); while(!q.empty()) { Node u=q.top(); q.pop(); if(vis[u.x])continue; vis[u.x]=1; for(int i=head[u.x];i!=-1;i=ne[i]) { if(dis[e[i]]>dis[u.x]+w[i]) { dis[e[i]]=dis[u.x]+w[i]; Node v(dis[e[i]],e[i]); q.push(v); } } } }
首先定义大根堆
跟图有关,那我们就得使出万能且高效的BFS。
如你所见,里面有一个BFS遍历。
while循环的前四行为基操,不做过多讲述,我们来看for循环。
for(int i=head[u.x],i!=-1;i=ne[i])//从头开始,循环到下一个点
从第x个点的链下标出发,向下一个点,也就是
if(dis[e[i]]>dis[u.x]+w[i]) { dis[e[i]]=dis[u.x]+w[i]; Node v(dis[e[i]],e[i]); q.push(v); }
这里我们做出判断,如果新路径的边权总和小于原路径边权总和,就改变最佳路径。
完整代码
这里附上完整代码:
#include<bits/stdc++.h> #define MOD 10000000007 #define INF 0x3f3f3f3f using namespace std; const int maxn=2000005; int n,m,s; int idx=1,e[maxn],w[maxn],head[maxn],ne[maxn]; int dis[maxn],vis[maxn]; struct Node { int dis,x; bool operator<(Node p)const{return dis>p.dis;} Node(int dis,int x):dis(dis),x(x){} }; inline int read() { int date=0,w=1; char c; c=getchar(); 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; } void add(int a,int b,int c) { e[idx]=b; w[idx]=c; ne[idx]=head[a]; head[a]=idx++; } void dijstra() { memset(dis,INF,sizeof(dis)); priority_queue<Node>q; dis[s]=0; Node u(dis[s],s); q.push(u); while(!q.empty()) { Node u=q.top(); q.pop(); if(vis[u.x])continue; vis[u.x]=1; for(int i=head[u.x];i!=-1;i=ne[i]) { if(dis[e[i]]>dis[u.x]+w[i]) { dis[e[i]]=dis[u.x]+w[i]; Node v(dis[e[i]],e[i]); q.push(v); } } } } signed main() { memset(head,-1,sizeof(head)); n=read(),m=read(),s=read(); for(int i=1;i<=m;i++) { int a=read(),b=read(),c=read(); add(a,b,c); } dijstra(); for(int i=1;i<=n;i++) cout<<dis[i]<<" "; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!