关于 Bellman-Ford 与 Floyd 算法的一点感想
2016-11-18 07:49
344 查看
在四种常用的最短路算法 Dijkstra, SPFA, floyd, Bellman-Ford 中, Dijks 和 SPFA 的使用较为普遍, 对大多数人来说, 也较为熟悉. 然而, floyd 与 BF 算法在一些特定的情况下也是非常管用的, 因此有必要在这里作出一点总结.
Floyd的基本思路就是枚举任意两个点i, j, 再枚举任意的第三个点k, 用d[i][k] + d[j][k] 来松弛d[i][j]的值. 时间复杂度为O(n ^ 3), 优点在于可以求出任意两点之间的距离, 在稠密图中也非常管用.
Bellman-Ford是SPFA算法的前身, 时间复杂度为O(VE)…非常慢, 但是可以用于判断负权回路. 常用于差分约束系统中. Bellman-Ford这种写法相当暴力, 直接循环nodeNum次, 每次枚举每一条边, 假如这条边可以用于松弛源点到端点的距离, 则进行松弛. 至于判断负环, 再枚举一遍所有边, 假如存在边仍能用于松弛, 则说明存在负权回路.
Floyd的基本思路就是枚举任意两个点i, j, 再枚举任意的第三个点k, 用d[i][k] + d[j][k] 来松弛d[i][j]的值. 时间复杂度为O(n ^ 3), 优点在于可以求出任意两点之间的距离, 在稠密图中也非常管用.
#include<iostream> #include<vector> using namespace std; const int &INF=100000000; void floyd(vector<vector<int> > &distmap,//可被更新的邻接矩阵,更新后不能确定原有边 vector<vector<int> > &path)//路径上到达该点的中转点 //福利:这个函数没有用除INF外的任何全局量,可以直接复制! { const int &NODE=distmap.size();//用邻接矩阵的大小传递顶点个数,减少参数传递 path.assign(NODE,vector<int>(NODE,-1));//初始化路径数组 for(int k=1; k!=NODE; ++k)//对于每一个中转点 for(int i=0; i!=NODE; ++i)//枚举源点 for(int j=0; j!=NODE; ++j)//枚举终点 if(distmap[i][j]>distmap[i][k]+distmap[k][j])//不满足三角不等式 { distmap[i][j]=distmap[i][k]+distmap[k][j];//更新 path[i][j]=k;//记录路径 } } void print(const int &beg,const int &end, const vector<vector<int> > &path)//传引用,避免拷贝,不占用内存空间 //也可以用栈结构先进后出的特性来代替函数递归 { if(path[beg][end]>=0) { print(beg,path[beg][end],path); print(path[beg][end],end,path); } else cout<<"->"<<end; } int main() { int n_num,e_num,beg,end;//含义见下 cout<<"(不处理负权回路)输入点数、边数:"; cin>>n_num>>e_num; vector<vector<int> > path, distmap(n_num,vector<int>(n_num,INF));//默认初始化邻接矩阵 for(int i=0,p,q; i!=e_num; ++i) { cout<<"输入第"<<i+1<<"条边的起点、终点、长度(100000000代表无穷大,不联通):"; cin>>p>>q; cin>>distmap[p][q]; } floyd(distmap,path); cout<<"计算完毕,可以开始查询,请输入出发点和终点:"; cin>>beg>>end; cout<<"最短距离为"<<distmap[beg][end]<<",打印路径:"<<beg; print(beg,end,path); }
Bellman-Ford是SPFA算法的前身, 时间复杂度为O(VE)…非常慢, 但是可以用于判断负权回路. 常用于差分约束系统中. Bellman-Ford这种写法相当暴力, 直接循环nodeNum次, 每次枚举每一条边, 假如这条边可以用于松弛源点到端点的距离, 则进行松弛. 至于判断负环, 再枚举一遍所有边, 假如存在边仍能用于松弛, 则说明存在负权回路.
#include<iostream> #include<cstdio> using namespace std; #define MAX 0x3f3f3f3f #define N 1010 int nodenum, edgenum, original; //点,边,起点 typedef struct Edge //边 { int u, v; int cost; }Edge; Edge edge ; int dis , pre ; bool Bellman_Ford() { for(int i = 1; i <= nodenum; ++i) //初始化 dis[i] = (i == original ? 0 : MAX); for(int i = 1; i <= nodenum - 1; ++i) for(int j = 1; j <= edgenum; ++j) if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛(顺序一定不能反~) { dis[edge[j].v] = dis[edge[j].u] + edge[j].cost; pre[edge[j].v] = edge[j].u; } bool flag = 1; //判断是否含有负权回路 for(int i = 1; i <= edgenum; ++i) if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost) { flag = 0; break; } return flag; } void print_path(int root) //打印最短路的路径(反向) { while(root != pre[root]) //前驱 { printf("%d-->", root); root = pre[root]; } if(root == pre[root]) printf("%d\n", root); } int main() { scanf("%d%d%d", &nodenum, &edgenum, &original); pre[original] = original; for(int i = 1; i <= edgenum; ++i) { scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost); } if(Bellman_Ford()) for(int i = 1; i <= nodenum; ++i) //每个点最短路 { printf("%d\n", dis[i]); printf("Path:"); print_path(i); } else printf("have negative circle\n"); return 0; }
相关文章推荐
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- HDU 1874 畅通工程续 (Dijkstra , Floyd , SPFA, Bellman_Ford 四种算法)
- 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson
- Floyd Dijkstra Bellman-Ford spfa 四种最短路经典算法汇总 HDU 2544为例
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson,无一幸免
- 多路径路由算法选择(7)——最短路径算法Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson
- hdu 1217 Arbitrage 两种算法AC代码,Floyd+Bellman-Ford 大水题一枚 注意是有向图~~
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 借ACM一道题 关于算法优化的一点感想
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- HDU 1874 畅通工程续 (Dijkstra , Floyd , SPFA, Bellman_Ford 四种算法)
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 几大最短路径算法比较(Floyd & Dijkstra & Bellman-Ford & SPFA)
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较(转)