多源最短路径Floyd算法
2016-03-31 19:54
417 查看
多源最短路径是求图中任意两点间的最短路,采用动态规划算法,也称为Floyd算法。将顶点编号为0,1,2...n-1首先定义dis[i][j][k]为顶点 i 到 j 的最短路径,且这条路径只经过最大编号不超过k的顶点。于是我们最终要求的是dis[i][j][n-1].状态转移方程如下:
dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]};
状态转移方程的解释:在计算dis[i][j][k]的时候,我们考虑 i 到 j 是否要经过顶点 k ,若不经过顶点 k ,那么结果就是 i 到 j 的最大路径经过的最大顶点不超过 k-1,也就是dis[i][j][k-1].倘若 i 到 j 经过顶点 k,那么i到j可以分为两部分之和,即 i 到k 和 k 到 j.这时候子问题最优解是 dis[i][k][k-1]和dis[k][j][k-1],这种情况下得到的原问题最优解是dis[i][k][k-1]+dis[k][j][k-1].所以综合起来: dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]};
在实现的时候没有必要使用三维数组。可以采用覆盖的方法:从k=0 to n-1 来计算,状态方程改变如下:
dis[i][j]=min{dis[i][j],dis[i][k]+dis[k][j]};
dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]};
状态转移方程的解释:在计算dis[i][j][k]的时候,我们考虑 i 到 j 是否要经过顶点 k ,若不经过顶点 k ,那么结果就是 i 到 j 的最大路径经过的最大顶点不超过 k-1,也就是dis[i][j][k-1].倘若 i 到 j 经过顶点 k,那么i到j可以分为两部分之和,即 i 到k 和 k 到 j.这时候子问题最优解是 dis[i][k][k-1]和dis[k][j][k-1],这种情况下得到的原问题最优解是dis[i][k][k-1]+dis[k][j][k-1].所以综合起来: dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]};
在实现的时候没有必要使用三维数组。可以采用覆盖的方法:从k=0 to n-1 来计算,状态方程改变如下:
dis[i][j]=min{dis[i][j],dis[i][k]+dis[k][j]};
#include<iostream> using namespace std; #define MAX_NUMBER INT_MAX/2 #define MAX_SIZE 100 struct Graph { int V, E; int R[MAX_SIZE][MAX_SIZE]; }; int path[MAX_SIZE][MAX_SIZE]; int dis[MAX_SIZE][MAX_SIZE]; void Floyd(Graph G); void PrintPath(int i, int j); int main() { Graph G; int i, j, w,k; cin >> G.V >> G.E; for (i = 0; i < G.V; i++) for (j = 0; j < G.V; j++) { G.R[i][j] = (i == j ? 0 : MAX_NUMBER); path[i][j]=i; //假设i到j有直接路径 } //--------------------------------初始化 for (k = 0; k < G.E; k++) { cin >> i >> j >> w; G.R[i][j] = G.R[j][i] = w; } Floyd(G); for (i = 0; i < G.V; i++) { for (j = 0; j < G.V; j++) printf("%3d", dis[i][j]); cout << endl; } printf("\n"); for (i = 0; i < G.V; i++) { for (j = 0; j < G.V; j++) printf("%3d", path[i][j]); cout << endl; } PrintPath(0,9); return 0; } void Floyd(Graph G) { int i, j, k; for (i = 0; i < G.V; i++) for (j = 0; j < G.V; j++) dis[i][j] = G.R[i][j]; //初始化 for (k = 0; k < G.V; k++) for (i = 0; i < G.V; i++) for (j = 0; j < G.V;j++) if (dis[i][j]>dis[i][k] + dis[k][j]) { //更新 path[i][j] = k; dis[i][j] = dis[i][k] + dis[k][j]; } } void PrintPath(int i, int j) { if (i==j) { printf("%3d", i); return; } PrintPath(i,path[i][j]); printf("%3d", j); }
相关文章推荐
- I.MX6 PMU MMPF0100 driver porting
- Java集合框架
- 线程池、ThreadLocal、Tomcat 应用小结
- Firefox上运行自动化测试脚本提示元素无法点击“WebDriverException: Message: Element is not clickable at point“解决方法
- git 从远程主服务器当中创建新分支
- PHP函数split()
- 硬件电路设计流程及步骤
- [转] iOS中文版资源库,非常全
- 2016sdau课程练习专题一 1005 problemF
- acm 1007 接力问题
- 枚举和#define宏之间的区别
- 1、开启Mysql的慢查询日志
- 3.1趣味整数之亲密数
- [总结]视音频编解码技术零基础学习方法
- 访谈录#1:成为“温赵轮”
- C++实验2-标准体重
- 游戏中的角色类2
- 在项目当中如何对UIButton进行重新布局
- 程序员适合哪些社区?
- poj1509 最小表示法