最短路模板——dijksttra(注意事项和易错点)
关于dijkstra
主要使用优先队列进行优化,时间复杂度为O(\(m log n\))。
对于稠密图来说,可以使用原版dijkstra,时间复杂度为O(\(n^2\))
以下是标准代码。
标准代码1:(加队列优化)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<iomanip>
#define N 100002
#define M 200002
using namespace std;
long long n,m,st,head[N],go[M],nxt[M],w[M],d[N],tot=0;
bool v[N];
priority_queue<pair<long long,long long> > q;
long long read(){
long long x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(long long)(ch-'0');ch=getchar();}
return x*h;
}
void add(long long x,long long y,long long z){
go[++tot]=y;nxt[tot]=head[x];head[x]=tot;w[tot]=z;
return ;
}
void dijkstra(){
memset(v,0,sizeof(v));
memset(d,0x3f,sizeof(d));
q.push(make_pair(0,st));d[st]=0;
while(!q.empty()){
long long x=q.top().second;q.pop();
if(v[x])continue;
v[x]=1;
for(long long i=head[x];i;i=nxt[i]){
long long y=go[i];
if(d[x]+w[i]>=d[y])continue;
d[y]=d[x]+w[i];
q.push(make_pair(-d[y],y));
}
}
return ;
}
int main(){
n=read();m=read();st=read();
for(long long i=1;i<=m;i++){
long long x=read(),y=read(),z=read();
add(x,y,z);
}
dijkstra();
for(long long i=1;i<=n;i++)printf("%lld ",d[i]);
return 0;
}
对于此代码来说,需要注意以下几点
if(v[x])continue; v[x]=1;必须写在循环外侧。因为在一张图中,同一个点的值可能被更新多次,但是当优先队列将其取出时,一定是最小的,所以如果之前已经出过队,就没有必要再次从这个点出发更新其他点。(划重点!!!)- 需要使用优先队列来做,pair<int,int>在优先队列中是按first值排序的。
- 从简洁性来考虑,取出队头时应写成
long long x=q.top().second;,而不是pair<long long,long long> x=q.top();。 - 在最后用
long long替换int时,要注意将printf中%d改为%lld。 priority_queue<int> q是大根堆,堆头是最大值。priority<int,vector<int>,greater<int> > q是小根堆,但这种小根堆只能使用int或long long,不能使用pair<int,int>。
标准代码2:(原版)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<iomanip>
#define N 1002
#define MAX 4557430888798830399
using namespace std;
long long n,m,st,mp[N][N],d[N];
bool v[N];
long long min(long long a,long long b){
return a<b ? a:b;
}
long long read(){
long long x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(long long)(ch-'0');ch=getchar();}
return x*h;
}
void dijkstra(){
memset(v,0,sizeof(v));
memset(d,0x3f,sizeof(d));
d[st]=0;
for(long long i=1;i<n;i++){
long long x=0;
for(long long j=1;j<=n;j++){
if((!v[j])&&(x==0||d[j]<d[x]))x=j;
}
v[x]=1;
for(long long j=1;j<=n;j++){
d[j]=min(d[j],d[x]+mp[x][j]);
}
}
return ;
}
int main(){
memset(mp,0x3f,sizeof(mp));
n=read();m=read();st=read();
for(int i=1;i<=n;i++)mp[i][i]=0;
for(long long i=1;i<=m;i++){
long long x=read(),y=read(),z=read();
mp[x][y]=min(mp[x][y],z);
}
dijkstra();
for(long long i=1;i<=n;i++){
if(d[i]==MAX)printf("2147483647 ");
else printf("%lld ",d[i]);
}
return 0;
}
对于此代码来说,需要注意以下几点:
- 注意邻接矩阵的初值。
- 在找最小值中,一定要加
x==0的判断
以上两组标准代码分别以P3371 【模板】单源最短路径(弱化版)和P4779 【模板】单源最短路径(标准版)为模板

浙公网安备 33010602011771号