首页 > 代码库 > 最短路
最短路
多源最短路
Floyd
时间复杂度:O(n3);空间复杂度:O(n2)
1 for(int k=1;k<=n;k++)2 for(int i=1;i<=n;i++)3 for(int j=1;j<=m;j++)4 map[i][j]=min(map[i][j],map[i][k]+map[k][j];
单源最短路
SPFA
初始化最短路径表;
源点入队;
取出队首点;
枚举取出点的边;
如果能松弛,就松弛,并把被松弛的点加入队列;
如此循环直到队列为空。
1 #include<cstdio> 2 int n,m,s,v[10010]; 3 int a,b,c; 4 int q[500010],head,tail; 5 int h[10010],hs; 6 struct edge{int s,n,v;}e[500010]; 7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0; } 8 int main(){ 9 scanf("%d%d%d",&n,&m,&s);10 for(int i=1;i<=n;i++) if(i!=s) v[i]=2147483647;11 for(int i=1;i<=m;i++){12 scanf("%d%d%d",&a,&b,&c);13 e[++hs]=(edge){b,h[a],c};14 h[a]=hs;15 }16 q[head++]=s;17 while(head>tail){18 a=q[tail++];19 for(int i=h[a];i;i=e[i].n){20 if(rel(v[e[i].s],v[a],e[i].v)){21 q[head++]=e[i].s;22 v[e[i].s]=v[a]+e[i].v;23 }24 }25 }26 for(int i=1;i<=n;i++) printf("%d ",v[i]);27 return 0;28 }
适用于各种找单源最短路的题目;
适用于负权图;
可以根据判断节点的入队次数来判断图是否有负权回路。eg:泥泞的道路
时间复杂度O(ke),理论复杂度高于Dijkstra,但有玄学加速。eg:【模板】单源最短路径*
优化:
SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。
LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。
SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。
并未使用过,因为SPFA在时间上很优,一般不需要担心被卡常数。
Dijkstra
初始化最短路径表;
源点标记;
用源点的边松弛;
寻找距离最短的未被标记的点;
用这个点的边松弛;
如此循环n-1次。
1 #include<cstdio> 2 int n,m,s,w[10010]; 3 int a,b,c; 4 bool v[10010]; 5 int h[10010],hs; 6 struct edge{int s,n,v;}e[500010]; 7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0;} 8 int main(){ 9 scanf("%d%d%d",&n,&m,&s);10 for(int i=1;i<=n;i++) if(i!=s) w[i]=2147483647;11 for(int i=1;i<=m;i++){12 scanf("%d%d%d",&a,&b,&c);13 e[++hs]=(edge){b,h[a],c};14 h[a]=hs;15 }16 v[s]=1;17 for(int i=h[s];i;i=e[i].n) if(rel(w[e[i].s],0,e[i].v)) w[e[i].s]=e[i].v;18 for(int k=1;k<n;k++){19 a=2147483647;20 for(int i=1;i<=n;i++) if(!v[i]&&w[i]<a) a=w[i],b=i;21 v[b]=1;22 for(int i=h[b];i;i=e[i].n) if(rel(w[e[i].s],w[b],e[i].v)) w[e[i].s]=e[i].v+w[b];23 }24 for(int i=1;i<=n;i++) printf("%d ",w[i]);25 return 0;26 }
!不能用于负权图。
一般在OI中不太常用;
时间复杂度O(n2),理论上平均比SPFA更快,实际上被完虐了。。。
可以用堆优化,实现并不简单,然而优化效果也并不显然。
Bellman-Ford
时间复杂度O(ne),这个效率在OI中寸步难行,SPFA是其优化版。
可以用于负权图,可以判断一个图中是否有负权回路。
最短路
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。