普通的Dijkstra算法复杂度为n平方,当数据量稍大时就会超时,所以诞生了时间复杂度为nlogn的优先队列优化的Dijkstra算法。
原来版本有大量时间浪费在通过邻接矩阵找边和搜索当前最短路径中,而优化后的算法中,用结构体Edge存储边信息,省却了找有效边的麻烦。而且采用优先队列,可以快速找到最短路径,又省却一部分时间,所以在时间上具有极强的优越性。
贴一份代码,看输入部分代码相信应该可以看明白输入要求:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000010;
struct qnode{
int v;//结点编号
int c;//到起点距离
qnode(int _v=0,int _c=0):v(_v),c(_c){};
bool operator <(const qnode &r)const{
return c>r.c;
}
};
struct Edge{
int v,cost;//边的终点和权值
Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[maxn];//可以理解为二维的,每个E可以包含若干项,这些项是以当前编号点为起点,
//若干项边结构体(Edge)的v为终点,cost为权值的边
bool vis[maxn];//是否访问
int dist[maxn];//距离
void dijkstra(int n,int start)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
{
dist[i]=inf;
}
priority_queue<qnode> que;//按照结点到起点距离大小作为出队列依据,距离最近先出
//毕竟更新的时候是当前最短距离点作为中介更新其他点
while(!que.empty())
{
que.pop();
}
dist[start]=0;
que.push(qnode(start,0));
qnode tmp;
while(!que.empty())//广搜找通路
{
tmp=que.top();
que.pop();
int u=tmp.v;
if(vis[u]) continue;
vis[u]=true;
for(int i=0;i<E[u].size();i++)
{
int v=E[tmp.v][i].v;//以tmp为起点的所有边中,找到另一个端点(方便起见叫做终点)
//因为全部是边结构体,所以不需要遍历寻找,只要尝试更新就可以
//vector本身就是向量,里面包含许多项,这里依次选取第i条边
int cost=E[u][i].cost;
if(!vis[v]&&dist[v]>dist[u]+cost)//更新条件
{
dist[v]=dist[u]+cost;
que.push(qnode(v,dist[v]));//为了不重,要求!vis[v],而且处理完进入队列进行下一次筛选
}
}
}
}
void addedge(int u,int v,int w)
{
E[u].push_back(Edge(v,w));//输入边
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
dijkstra(n,1);
printf("%d\n",dist[n]);
return 0;
}