最短路
Posted bigyellowdog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路相关的知识,希望对你有一定的参考价值。
最短路
要求掌握Floyd,Dijkstra,SPFA
下面依次来讲解.......
1:Flyod
弗洛伊德(Floyd)是解决最短路径的算法,可以求出任意两点间的最短路径。
使用条件:
1:可以出现负边权
2:不是单源(只有一个起始点)算法
利与弊:
利:跑一次即可求出任意两点最短路径,且可以存在负边权
弊:时间复杂度不是一般的高,O(n的3方)
核心代码:
1 for(int k=1;k<=n;k++)
2 for(int i=1;i<=n;i++)
3 for(int j=1;j<=n;j++)
4 if(k!=i && i!=j && k!=j && dis[i][k]+dis[k][j]<dis[i][j])
5 dis[i][j]=dis[i][k]+dis[k][j];
//注意:dis[i][k]+dis[k][j]中的i、k、j的顺序不要写反了!
2:Dijkstra
迪杰斯特拉(Dijkstra)是处理最短路径的算法。可求出一点到任意点的最短路径
条件:
1:是单源算法
2:不能存在有负边权
利与弊:
利:时间复杂度较低,为O(n的2方)
弊:不能处理负边权,且只能处理一点到任意点距离
核心代码:
1 memset(dis,0x3f,sizeof(dis));
2 dis[start]=0;
3 int minn,k;
4 for(int i=1;i<=n;i++)
5 {
6 minn=0x3f,k=0;
7 for(int j=1;j<=n;j++)
8 {
9 if(!b[j] && dis[j]<minn)
10 {
11 minn=dis[j];
12 k=j;
13 }
14 }
15 if(k==0) break;
16 b[k]=1;
17 for(int j=head[k];j!=0;j=edge[j].next)
18 {
19 if(edge[j].w+dis[k]<dis[edge[j].to])
20 dis[edge[j].to]=edge[j].w+dis[k];
21 }
22 }
3:SPFA
SPFA算法是处理最短路径的一种算法,它不能处理负环回路
条件:
1:是单源算法
2:不能处理负环
利与弊:
利:时间复杂度低,可以说是几种最短路中最优的算法
弊:好像没有...
核心代码:
1 memset(dis,0x3f,sizeof(dis));
2 queue<int> zhou;
3 zhou.push(1); dis[1]=0; b[1]=1;
4 while(!zhou.empty())
5 {
6 int now=zhou.front(); zhou.pop(); b[now]=0;
7 for(int i=head[now];i!=0;i=edge[i].next)
8 {
9 if(dis[now]+edge[i].dis<dis[edge[i].to])
10 {
11 dis[edge[i].to]=dis[now]+edge[i].dis;
12 if(!b[edge[i].to])
13 {
14 b[edge[i].to]=1;
15 zhou.push(edge[i].to);
16 }
17 }
18 }
19 }
当然了,这里有几道题,可以去洛谷看看,并训练训练
https://www.luogu.org/blog/BigYellowDog/p2384-zui-duan-lu (SPFA模版题)
https://www.luogu.org/blog/BigYellowDog/p2910-usaco08open-xun-bao-zhi-lu-clear-and-present-danger (Floyd模版题)
https://www.luogu.org/blog/BigYellowDog/p1346-dian-ju (最短路变式题)
以上是关于最短路的主要内容,如果未能解决你的问题,请参考以下文章