3种求最短路的方法
来源:互联网 发布:秦始皇活着吗 知乎 编辑:程序博客网 时间:2024/05/16 07:29
最短路
这几天做题,碰见了很多最短路的题目,于是就在博客里发一下3种比较常用的算法。
In order to 方便以后自己看……
备注:n为点数,m为边数
Dijkstra
复杂度O(n^2)
适用于没有负权边的图,主要作用是单源求最短路
特点:复杂度稳定
思想:
①先拓展出起始点v0
②把与v'相邻的所有未拓展出的点的d更新(设拓展出来的是v'' 则d[v'']=min(d[v''],d[v']+dis[v'][v'']))
③找出已拓展出来的所有点相邻的距离最短的点v'(此处可以堆优化),并且拓展出来
④循环②③直到所有点都被拓展出来
代码(没有堆优化且写法繁琐,使用了邻接表)(以后会了,会补上有堆优化的)
#include <cstring>#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <stack>#define inf 0x3fusing namespace std;void fre(){freopen(".in","r",stdin);freopen(".out","w",stdout);}const int maxn=1000,maxm=10000;struct Edge{int v,next,l;}edge[maxm];int head[maxn],cnt=1;int n,m;void addedge(int a,int b,int L){edge[cnt].next=head[a];edge[cnt].v=b;edge[cnt].l=L;head[a]=cnt++;}int dis[maxn];bool vis[maxn];void dijkstra(int start,int d[]){d[start]=0;vis[start]=true;for(int i=head[start];i!=-1;i=edge[i].next){int y=edge[i].v,dist=edge[i].l;d[y]=dist;}for(int k=1;k<n;k++){int MIN=0;for(int i=1;i<=n;i++){if(!vis[i] && d[i]<d[MIN]){MIN=i;}}vis[MIN]=true;for(int i=head[MIN];i!=-1;i=edge[i].next){int x=MIN,y=edge[i].v,dist=edge[i].l;if(!vis[y] && d[x]+dist<d[y]){d[y]=d[x]+dist;}}}}void init(){memset(head,-1,sizeof(head));memset(dis,inf,sizeof(dis));}int main(){init();scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y,L;scanf("%d%d%d",&x,&y,&L);addedge(x,y,L);addedge(y,x,L);}int start;scanf("%d",&start);dijkstra(start,dis);for(int i=1;i<=n;i++)printf("%d %d\n",i,dis[i]);return 0;}
Floyd
复杂度O(n^3)
适用于求出每两个点的最短路距离
主要代码:
for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
思想:
此(上面代码)中有真意,欲辨已忘言!
代码
#include <cstring>#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <stack>#define inf 0x3f3f3f3fusing namespace std;void fre(){freopen(".in","r",stdin);freopen(".out","w",stdout);}const int maxn=1000;int f[510][510];int gmin(int a,int b){return a<b ? a: b;}int n,m;int main(){//fre();memset(f,inf,sizeof(f));scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y,l;scanf("%d%d%d",&x,&y,&l);f[x][y]=f[y][x]=l;}for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)f[i][j]=gmin(f[i][j],f[i][k]+f[k][j]);for(int i=1;i<=n;i++)f[i][i]=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)printf("%d ",f[i][j]);puts("");}return 0;}
SPFA
复杂度:O(k*m)(k为所有点的平均进队次数)
适用于有负边的图,但是不能有负环,主要作用是单源求最短路
特点:复杂度不稳定
基本思想:
①弹出队头的点,访问它所连的点
②如果d[y]>d[x]+l,则执行
d[y]=d[x]+l
再看y是否在队列中,如果不再就把y进队
③知道队列为空
代码(用了系统队列)
</pre><p><pre name="code" class="cpp">#include <bits/stdc++.h>#define inf 0x3fusing namespace std;void fre(){freopen(".in","r",stdin);freopen(".out","w",stdout);}const int maxn=510,maxm=10010;struct Edge{int to,next,L;}edge[maxn];int head[maxn],cnt=0;int n,m;void addedge (int u,int v,int l){cnt++;edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].L=l;head[u]=cnt;}int dis[maxn];bool vis[maxn];queue <int> que;int c[maxn];void spfa(int start,int d[]){que.push(start);vis[start]=true;c[start]=1;d[start]=0;while(!que.empty()){int x=que.front();que.pop();vis[x]=false;for(int i=head[x];i!=-1;i=edge[i].next){int y=edge[i].to,l=edge[i].L;if(d[y]>d[x]+l ){d[y]=d[x]+l;if(!vis[y]){que.push(y);vis[y]=true;c[y]++;if(c[y]>n){puts("-1");return ;}}}}}}void init(){memset(head,-1,sizeof(head));memset(dis,0x3f,sizeof(dis));}int main(){init();scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y,l;scanf("%d%d%d",&x,&y,&l);addedge(x,y,l);addedge(y,x,l);}int X;scanf("%d",&X);spfa(X,dis);for(int i=1;i<=n;i++)printf("%d\n",dis[i]);return 0;}
0 0
- 3种求最短路的方法
- 最短路的方法总结
- 求最短路的相关方法
- 最短路的解题方法区别
- JTAG的TCK和GND短路补救方法
- zoj 1221 Risk【最短路 3种方法】
- 【最短路】最短路上的统计
- 【最短路】poj3660 最短路的应用
- 短路和非短路的"与"、"或"
- js短路,||、&&、!!短路运算符的使用
- 浅论3大方法求单源最短路以及2大方法求最小生成树
- 美丽的短路原则
- 逻辑运算的短路现象
- &&的短路原理
- 逻辑运算的短路问题
- &&的短路特性
- 最短路的小结
- 逻辑运算的短路特征
- clion undefined reference to `boost::system::generic_category()'
- 【贪心算法】区间调度问题总结
- Spring Data Jpa 自定义方法实现问题
- 51nod1006 最长公共子序列Lcs
- ARC机制的基本规则及强制规定
- 3种求最短路的方法
- Delphi TDataSetProvider的Option属性
- 【51Nod】1102 - 面积最大的矩形面积(单调栈)
- 所有HTTP返回码
- VirtualBox安装CentOS 7(三)
- 安卓学习笔记---Android 中如何关闭Thread线程
- 浅谈CSRF攻击方式
- Oracle中的order by分页排序问题
- 拆解Cluene系列(4)——store中的类图