Dijkstra算法之优先队列优化版本 By ACReaper Dijkstra

Dijksta算法中,如果我们采用的是邻接矩阵来存的,第一点浪费的空间比较多,第二点我们知道算法的时间复杂度在O(n*n),这样的算法可以说并不是很好,所以我们考虑优化它,那么可以从哪些地方优化呢,首先我们可以优化存储结构,采用邻接表来存储,其次我们可以用优先队列来排序大小,其时间复杂度大大降低。代码如下。

需要注意的是pair是按照第一个元素的大小排序,如果相同才按照第二个,所以我们要把d[i]包装在第一个元素上。

还有这里必须掌握C++的优先队列容器,当然如果你要自己写,也可以,但是没有那个必要。这里的优先队列是这样的,有三个参数,第一个就是队列存的元素的数据类型,第二个我们用vector数组自动实现拓展,第三个是一个可选的排序方式,可以自己定义,也可以用默认的是 <,,代表着按照升序排列,优先队列中pop指向最后,top也是,push指向最前面。


#include <cstdio>
#include <cstring>
#include <limits>
#include <queue>
#define MAXN 1000
using namespace std;
int n,m;
int next[MAXN + 1];//表示第i条边的nexr指针 
int first[MAXN + 1];//表示第i个结点的next指针 
int u[MAXN + 1],v[MAXN + 1];
int w[MAXN + 1];
int d[MAXN + 1];//用来表示到结点V1的最短长度
int fa[MAXN + 1];//用来记录路径 
typedef pair<int,int> pii;
int main(){
	
	while(scanf("%d%d",&n,&m) != EOF){
		
		for(int i = 1; i <= n ; i++){
			first[i] = 0;
		}
		
		for(int e = 1; e <= m; e++){//建立图的邻接表 
			scanf("%d%d%d",&u[e],&v[e],&w[e]);
			next[e] = first[u[e]];
			first[u[e]] = e; 
		}
		
		d[1] = 0,fa[1] = 1;//Init Dijkstra 
		const int inf = std::numeric_limits<int>::max();
		for(int i = 2; i <= n; i++){
			d[i] = inf;
			fa[i] = 0;
		}
		
		priority_queue <pii,vector<pii>,greater<pii> >q;//优先队列
		bool done[MAXN + 1];
		memset(done,0,sizeof(done));//初始化done
		q.push(make_pair(d[1],1));
		while(!q.empty()){
			pii u = q.top();
			q.pop();
			int x = u.second;
			if(done[x]) continue;
			done[x] = true;
			for(int e = first[x]; e != 0; e = next[e]){//由邻接表出发拓展于其相邻的结点 
				
				if(d[v[e]] > d[x] + w[e]){
					d[v[e]] = d[x] + w[e];
					fa[v[e]] = x;
					q.push(make_pair(d[v[e]],v[e]));
				} 
				
			}
		}
		
		for(int i = 1; i <= n; i++){
			printf("%d ",d[i]);
		} 
	}
	return 0;
}

这段代码的效率大大的提高了。

2013 04 29

By ACReaper


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值