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