Dijkstra算法

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; 
} 
点赞