Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
算法流程:
1.初始化vis[1-n]为0和d数组初始化为无穷大,d[1]=0。
2.然后从1-n中找出一个未被标记且d[x]最小的节点x,然后标记x为已经标记x,vis[x]=1.
3.扫描x的所有出边,然后更新d数组,d[j]=min(d[j],d[x]+map[x][j]);(j从1-n).
4.重复进行2,3步骤直到n-1次就更新完毕.
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=3010;
int n,m;
int vis[N];
int map[N][N];
int d[N];
void dijkstra(){
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
d[1]=0;
for(int i=1;i<n;i++){
int x=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&(x==0||d[j]<d[x])) x=j;
vis[x]=1;
for(int j=1;j<=n;j++)
d[j]=min(d[j],d[x]+map[x][j]);
}
}
int main(){
cin>>n>>m;
memset(map,0x3f,sizeof(map));
for(int i=1;i<=n;i++) map[i][i]=0;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
// scanf("%d%d%d",&x,&y,&z);
map[x][y]=z;
map[y][x]=z;
}
dijkstra();
for(int i=1;i<=n;i++)
cout<<d[i]<<endl;
return 0;
}
然后上一道dijkstra算法的基础模板题 hdu2544
上述算法的时间复杂度为o(n^2),每次都是暴力寻找d数组中的最小值,可以用优先队列(c++ STL priority_queue)进行优化,最终用mlogn的时间复杂度内实现dijkstra算法。
c++ STL priority_queue为大根堆,存的时候将距离的相反数存入堆中,这样就相当于把小的放入堆顶,相当于变成小根堆。
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int N=10010,M=1000010;
int n,m,tot;
int vis[N];
int map[N][N];
int d[N];
priority_queue<pair<int,int>> q;
int head[N],ver[M],edge[M],nex[M];
void dijkstra(){
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
d[1]=0;
q.push(make_pair(0,1));
while(q.size()){
int x=q.top().second;
q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=nex[i]){
int y=ver[i],z=edge[i];
if(d[y]>d[x]+z){
d[y]=d[x]+z;
q.push(make_pair(-d[y],y));
}
}
}
}
void add(int x,int y,int z){
ver[++tot]=y,edge[tot]=z,nex[tot]=head[x],head[x]=tot;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dijkstra();
for(int i=1;i<=n;i++)
cout<<d[i]<<endl;
return 0;
}