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