优化原因
在上一张博客,讲到了dijstra算法,现在,我们对这一算法进行优化
首先:在查找最小dis时用优先队列优化的小根堆使得最小的dis自动上浮到堆顶(原先需用for遍历,复杂度为o(n))
其次:使用链式前向星,缩小所搜索的点的范围,以前需要用for对每个点遍历,现在只用考虑head【】连接的几个点;进一步只搜索距离可以被更新的点,将这几个点加入小根堆
代码贴示如下:
#include<bits/stdc++.h>
#include<queue>
using namespace std;
struct n{
int w,to,from;
}edge[10000000];//链式前向星
struct node{
int pos;
int dis;
bool operator <(const node &a)const
{
return a.dis<dis;//小根堆
}
};
int head[100000];
int cnt,dis[1000000],vis[1000000];
void add(int u,int v,int w){
cnt++;
edge[cnt].w=w;
edge[cnt].to=v;
edge[cnt].from=head[u];
head[u]=cnt;
}
priority_queue<node>q;
int main(){
int n,m,s;
cin>>n>>m>>s;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
for(int i=1;i<=n;i++)
dis[i]=0x7fffffff;//初始化dis
dis[s]=0;
q.push((node){s,0});
while(!q.empty()){
node sign=q.top();//最适合的点自动上浮
q.pop();
int x=sign.pos;int d=sign.dis;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=edge[i].from){
int y=edge[i].to;
if(dis[y]>dis[x]+edge[i].w)
{
dis[y]=dis[x]+edge[i].w;
if(!vis[y]) q.push((node){y,dis[y]});//可更新的点压入队列
}
}
}
for(int i=1;i<=n;i++)
cout<<dis[i]<<" ";
}