总结一下最短路径的贝尔曼-福特算法(Bellman-Ford)及用队列优化(spfa)
2017-01-16 17:45
771 查看
关于贝尔曼福特算法:
百度百科:贝尔曼-福特算法
------------------------------------------------------------------------------------------------分割线---------------------------------------------------------------------------------------------
关于贝尔曼福特算法,假设有n个顶点,我们只需要遍历n-1轮就可以了,因为在一个含n个顶点的图中,任意两点之间的最短路径最多含有n-1条边, 什么原理,我就不讲了,网上大牛博客很多,我在这里上一点干货:
1.最原始的贝尔曼福特算法,时间复杂度为O(NM):
有时候在n-1轮松弛之前就已经算出了最短路,这时候我们可以判断一下来进行优化:
对于上面的代码,给出两组样例:
在最短路算法对比:
百度百科:贝尔曼-福特算法
------------------------------------------------------------------------------------------------分割线---------------------------------------------------------------------------------------------
关于贝尔曼福特算法,假设有n个顶点,我们只需要遍历n-1轮就可以了,因为在一个含n个顶点的图中,任意两点之间的最短路径最多含有n-1条边, 什么原理,我就不讲了,网上大牛博客很多,我在这里上一点干货:
1.最原始的贝尔曼福特算法,时间复杂度为O(NM):
#include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <stack> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define maxnum 3010 #define inf 0x3f3f3f using namespace std; int main() { int dis[10],n,m,u[10],v[10],w[10]; //读入顶点个数和边的条数 scanf("%d%d",&n,&m); //读入边 for(int i=1; i<=m; i++) scanf("%d%d%d",&u[i],&v[i],&w[i]); //初始化dis数组 for(int i=1; i<=n; i++) dis[i]=inf; dis[1]=0; //贝尔曼-福特算法(Bellman-Ford)的核心语句 for(int k=1; k<=n-1; k++) for(int i=1; i<=m; i++) if(dis[u[i]]+w[i]<dis[v[i]]) dis[v[i]]=dis[u[i]]+w[i]; //输出结果 for(int i=1;i<=n;i++) printf("%d ",dis[i]); }这个算法还可以用来检测一个图是否含有负权回路,如果进行了n-1轮松弛操作后仍然存在:
if(dis[u[i]]+w[i]<dis[v[i]]) dis[v[i]]=dis[u[i]]+w[i];如果这种情况持续存在,那么这个图一定含有负权回路。
有时候在n-1轮松弛之前就已经算出了最短路,这时候我们可以判断一下来进行优化:
#include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <stack> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define maxnum 3010 #define inf 0x3f3f3f using namespace std; int main() { int dis[10],n,m,u[10],v[10],w[10],check,flag; //读入顶点个数和边的条数 scanf("%d%d",&n,&m); //读入边 for(int i=1; i<=m; i++) scanf("%d%d%d",&u[i],&v[i],&w[i]); //初始化dis数组 for(int i=1; i<=n; i++) 4000 dis[i]=inf; dis[1]=0; //贝尔曼-福特算法(Bellman-Ford)的核心语句 for(int k=1; k<=n-1; k++) {check=0;//标记数组dis在本轮松弛中是否会发生更新 for(int i=1; i<=m; i++) if(dis[u[i]]+w[i]<dis[v[i]]) { dis[v[i]]=dis[u[i]]+w[i]; check=1;//数组dis发生更新,改变check的值 } //松弛完毕后检测dis是否有更新 if(check==0)break;//如果没有更新,提前退出循环 } //检测负权回路并输出结果 flag=0; for(int i=1; i<=m; i++) if(dis[u[i]]+w[i]<dis[v[i]]) flag=1; if(flag==1) printf("此图含有负权回路\n"); else { for(int i=1; i<=n; i++) printf("%d ",dis[i]); } }2.贝尔曼福特算法的队列优化,时间复杂度为O(N):
#include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <stack> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define maxnum 3010 #define inf 0x3f3f3f using namespace std; int dis[maxnum],n,m,u[maxnum],v[maxnum],w[maxnum]; int first[maxnum],next[maxnum],vis[maxnum]; int main() { queue<int>q; //读入顶点个数和边的条数 scanf("%d%d",&n,&m); //初始化dis数组 for(int i=1; i<=n; i++) dis[i]=inf; dis[1]=0; //初始化vis,刚开始不在队列中 for(int i=1; i<=n; i++) vis[i]=0; //初始化first的下标为-1,表示1~n号顶点暂时都没有边 for(int i=1; i<=n; i++) first[i]=-1; //读入边并建立邻接表 for(int i=1; i<=m; i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); next[i]=first[u[i]]; first[u[i]]=i; } //1号顶点入队 vis[1]=1; q.push(1); while(!q.empty()) { int k=first[q.front()]; while(k!=-1)//扫描当前顶点所有的边 { if(dis[u[k]]+w[k]<dis[v[k]])//判断是否松弛成功 { dis[v[k]]=dis[u[k]]+w[k];//更新顶点1到顶点v[k]的路程 if(vis[v[k]]==0)//判断一个顶点是否在队列中,为0表示不在队列,加入队列 { q.push(v[k]); vis[v[k]]=1;//同时标记顶点v[k]已经入队 } } k=next[k]; } vis[q.front()]=0; q.pop(); } //输出结果 for(int i=1; i<=n; i++) printf("%d ",dis[i]); return 0; }
对于上面的代码,给出两组样例:
输入: 5 5 2 3 2 1 2 -3 1 5 5 4 5 2 3 4 3 输出: 0 -3 -1 2 4 输入: 5 7 1 2 2 1 5 10 2 3 3 2 5 7 3 4 4 4 5 5 5 3 6 输出: 0 2 5 9 9
在最短路算法对比:
相关文章推荐
- 总结一下最短路径的贝尔曼-福特算法(Bellman-Ford)及用队列优化(spfa)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 求解最短路径Bellman_Ford 算法优化版——结合队列
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 单点最短路径算法 bellman-ford模板和队列优化后的spfa算法模板
- 最短路径算法(2)—Bellman-Ford(贝尔曼-福特)算法
- java实现图的最短路径(SP)的贝尔曼福特(Bellman-Ford)算法
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- Bellman-Ford(贝尔曼-福特)算法求单源最短路径
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- JAVA实践使用队列优化Bellman-Ford最短路径算法
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较(转)