求$1$-$n$的最短路,$n<=100000$,$m<=200000$。
最短路啥都忘了,得好好学一学QAQ
迪杰斯特拉是一种复杂度非常稳定的算法,时间复杂度为$(nm)$
算法的流程是每次找到一个未被更新的离起点最近的点,然后再用它去更新周围的点
这样我们能写出来朴素的迪杰斯特拉的代码:
1 void Dij() 2 { 3 memset(dis,127,sizeof(dis)); 4 dis[s]=0; 5 for(int i=1;i<=n;i++) 6 { 7 int node=0,minn=inf; 8 for(int j=1;j<=n;j++) 9 if(!vis[j]&&dis[j]<minn) 10 minn=dis[j],node=j; 11 if(!node) break; 12 vis[node]=true; 13 for(int j=head[node];j;j=e[j].next) 14 { 15 int to=e[j].to; 16 if(!vis[to]&&dis[to]>dis[x]+e[i].dis) dis[to]=dis[x]+e[i].dis; 17 } 18 } 19 }
然后这个算法它哪里慢了?就是在找离起点最近的那一个点上
所以就有了堆优化的迪杰斯特拉,原理是用堆存每个点离起点的距离,每次直接弹出最小的即可
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #define inf 2147483647 7 #define M 200010 8 using namespace std; 9 int n,m,S,num; 10 int dis[M],head[M]; 11 bool vis[M]; 12 struct point{int dis,to,next;}e[M<<1]; 13 struct node{int id,dis;}; 14 bool operator < (node a,node b) {return a.dis>b.dis;} 15 priority_queue<node>q; 16 void add(int from,int to,int dis) 17 { 18 e[++num].next=head[from]; 19 e[num].to=to; 20 e[num].dis=dis; 21 head[from]=num; 22 } 23 void Dijkstra() 24 { 25 memset(dis,127,sizeof(dis)); 26 dis[S]=0; 27 q.push((node){S,0}); 28 while(!q.empty()) 29 { 30 int x=q.top().id; q.pop(); 31 if(vis[x]) continue; 32 vis[x]=true; 33 for(int i=head[x];i;i=e[i].next) 34 { 35 int to=e[i].to; 36 if(!vis[to]&&dis[to]>dis[x]+e[i].dis) 37 { 38 dis[to]=dis[x]+e[i].dis; 39 q.push((node){to,dis[to]}); 40 } 41 } 42 } 43 } 44 int main() 45 { 46 scanf("%d%d%d",&n,&m,&S); 47 for(int i=1;i<=m;i++) 48 { 49 int x,y,z; scanf("%d%d%d",&x,&y,&z); 50 add(x,y,z); 51 } 52 Dijkstra(); 53 for(int i=1;i<=n;i++) printf("%d ",dis[i]); 54 return 0; 55 }