最短路模板-folyd bellman Dijkastra+路径还原+SPFA
来源:互联网 发布:ps4游戏卖给淘宝店家 编辑:程序博客网 时间:2024/05/26 07:27
以下所有算法都不能解决负圈的最短路,因为有负圈的路不存在最短路,但是只有Dijkstra不能处理带有负边的最短路。
一、先是最好理解的folyd算法
注意k在最外层,为什么k一定要在最外层?
假设k在最内层,那么从 i 到 j 的点 只确定一次最短路(k从1到n),过早地确定了 i 到 j的最短路,但如果把k放在外曾,k从1-n过程中,i 到 j 确定了 n次
贴一个讲解这个的博客 http://www.cnblogs.com/twjcnblog/archive/2011/09/07/2170306.html
1、解决任意两点的最短路情况
int n;int map[110][100];void floyd ()//以每个点为起点到每个点的最短路,(map表示边的权值,不存在边设为无穷大){ for(int k=1;k<=n;++k)//k一定在最外层 { for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) map[i][j]=min(map[i][j],map[i][k]+map[k][j]); }}
二、bellman- ford算法
1、解决单源最短路
以边的顺序计算最短路,最多进行V-1次
struct edge{ int from,to,cost;}es[maxn];int V,E;int d[maxn];//d【i】表示从s到i的最短路,初始值除d【s】外都为INFvoid bellman_ford(int s)//从s到每个点的最短路{ for(int i=0;i<V;++i) d[i]=INF; d[s]=0; while(1) { bool update = false;//判断是否全部更新完了 for(int i=0;i<E;++i) { edge e = es[i];//按顺序取出每一条边 if(d[e.from]!=INF && d[e.from]+e.cost < d[e.to]) { d[e.to] = d[e.from] + e.cost; update = true;//这一轮取所有边后有更新 } } if(!update) break; }}
2、利用上述性质可以判断是否有负圈,如果有负圈,会不断进行更新,那么将会超出v-1次
//bellman-ford判断存不存在负圈;bool find_negative_loop(){ memset(d,0,sizeof(d)); for(int i=1;i<V;++i) for(int j=0;j<E;++j) { edge e=es[j]; if(d[e.to]>d[e.from]+e.cost) { d[e.to] = d[e.from] +e.cost; if(i== V-1) return true;//第v-1次仍然进行了说明有负圈 } } return false;}
三、Dijkastra算法
Dijkastra是上一个算法的优化,将已经确定最短路的点去掉,只考虑没确定过最短路的点.这个不好理解,为什么是正确的就不证明了,贴一个讲的很好的博客 http://blog.csdn.net/mengxiang000000/article/details/50421243
我认为大概就是分为两步,第一步从尚未使用过的点中选取一个距离起点最近的点,第二步,把选取的点与之能到的点更新
1、单源最短路
//Dijkastra算法bool used[maxn];int d[maxn];void dijkastra( int s){ memset(d,INF,sizeof(d)); memset(used,0,sizeof(used)); d[s]=0; while(1) { int v=-1;//相当于bellman算法中的update,又有所不同 //第一步从尚未使用过的点中选取一个距离起点最近的点(第一次取得是起点s) for(int u=0;u<V;++u) { if(!used[u] && (v== -1 || d[u]<d[v])) v=u; } if(v==-1) break;//所有点都确定最小值了,无点可取 //第二步,把选取的点与之能到的点更新 else { used[v]= true;//把这个点标记 for(int u=0;u<V;++u) { d[u]=min(d[u],d[v]+map[v][u]); } } }}
2、还原路径
因为从i - j 的最短路 要么是直接通向,要么是一点点更新来的, 所以每次只需要记录当前点的最短是哪个点更新来的就可以。然后利用递归输出就可以,这里直接摘抄书上的代码,用的是dijkastra 算法 c++的vector实现的。
//Dijkastra算法还原路径bool used[maxn];int d[maxn];int prex[maxn];void dijkastra( int s){ memset(d,INF,sizeof(d)); memset(used,0,sizeof(used)); memset(prev,-1,sizeof(prev)); d[s]=0; while(1) { int v=-1;//相当于bellman算法中的update,又有所不同 //第一步从尚未使用过的点中选取一个距离起点最近的点(第一次取得是起点s) for(int u=0;u<V;++u) { if(!used[u] && (v== -1 || d[u]<d[v])) v=u; } if(v==-1) break;//所有点都确定最小值了,无点可取 //第二步,把选取的点与之能到的点更新 else { used[v]= true;//把这个点标记 for(int u=0;u<V;++u) { if(d[u]>d[v]+map[v][u]) { d[u]=d[v]+map[v][u]; prev[u]=v; } } } }}void get_path(int t){ vector<int> path; while(t!=-1) { path.push_back(t); t=prev[t]; } reverse(path.begin(),path.end()); return path;}
四、SPFA
SPFA(Shortest Path Faster Algorithm)(队列优化)算法是求单源最短路径的一种算法,它还有一个重要的功能是判负环(在差分约束系统中会得以体现),在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。
int map[maxn][maxn];int dis[maxn],visit[maxn];void init()//初始化map{ int i,j; for(i=0;i<maxn;++i) for(j=0;j<maxn;++j) { if(i==j) map[i][j]=0; map[i][j]=map[j][i]=INF; }}void spfa(int start){ queue<int> q; int i,now; memset(dis,INF,sizeof(dis)); memset(visit,0,sizeof(visit)); dis[start]=0; q.push(start); visit[start]=1; while(!q.empty()) { now=q.front(); q.pop(); visit[now]=0; for(i=1;i<maxn;++i) { if(dis[i]>dis[now]+map[now][i]) { dis[i]=dis[now]+map[now][i]; if(visit[i]==0) { q.push(i); visit[i]=1; } } } }}
1 0
- 最短路模板-folyd bellman Dijkastra+路径还原+SPFA
- Bellman Ford+SPFA队列优化(路径还原 输出最短路的路径)
- 最短路模板Dijkstra Bellman-Ford Floyd SPFA
- 【图论】【最短路径模板+邻接表】【Floyed+Dijsktra+Bellman-Ford+SPFA】【最短路算法对比分析】
- 最短路 SPFA模板
- 最短路 【spfa】 模板
- 最短路~spfa模板
- 最短路-SPFA 模板
- 模板-最短路//spfa
- 最短路路径还原
- hdu 2544 最短路(最短路径)(flody、dij、dij+priority queue、bellman、spfa)
- 蓝桥杯--最短路 -- Djikstra,Bellman-Frod,SPFA
- 最短路算法 Dijkstra Bellman-Ford SPFA
- 单源最短路径算法 Bellman-Ford && SPFA 及 最短路算法统一归纳
- 单源最短路径算法 Bellman-Ford && SPFA 及 最短路算法统一归纳
- hdu-2544-最短路(Dijkstra + Dijkstra优先队列 + Bellman-ford + SPFA +Floyd) 纯模板题
- Wormholes( POJ 3259)(Bellman-Ford+SPFA)(判断是否有负权环)(最短路模板)
- HDU 2544 最短路 floyd djkstra(邻接表,邻接矩阵) spfa bellman-ford 模板题
- 数据库学习日志
- JQuery常用选择器
- Java中Scanner类和BufferReader类之间的区别
- 14
- 使用smarty生成页面缓存
- 最短路模板-folyd bellman Dijkastra+路径还原+SPFA
- 不定期更新学习过程中碰到的小问题
- TypeError: __init__() takes exactly 2 arguments (3 given)
- 使用PL/SQL Developer工具来实现创建表空间、创建数据库、备份数据库、数据导出等操作
- 15
- 侧滑菜单的实现方式(一):自定乂控件
- SharePoint学习总结
- 7.2简单线性回归算法实现--python机器学习
- 《Motion Design for iOS》(四十四)