最短路径——Floyd-Warshall算法
Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。
我们平时所见的Floyd算法的一般形式如下:
void Floyd()
{
int i,j,k;
for(k=;k<=n;k++)
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if(dist[i][k]+dist[k][j]<dist[i][j])
dist[i][j]=dist[i][k]+dist[k][j];
}
注意下第6行这个地方,如果dist[i][k]或者dist[k][j]不存在,程序中用一个很大的数代替。最好写成if(dist[i][k]!=INF && dist[k][j]!=INF && dist[i][k]+dist[k][j]<dist[i][j]),从而防止溢出所造成的错误。
上面这个形式的算法其实是Floyd算法的精简版,而真正的Floyd算法是一种基于DP(Dynamic Programming)的最短路径算法。
例题分析:
设图G中n 个顶点的编号为1到n。令c [i, j, k]表示从i 到j 的最短路径的长度,其中k 表示该路径中的最大顶点,也就是说c[i,j,k]这条最短路径所通过的中间顶点最大不超过k。因此,如果G中包含边<i, j>,则c[i, j, 0] =边<i, j> 的长度;若i= j ,则c[i,j,0]=0;如果G中不包含边<i, j>,则c (i, j, 0)= +∞。c[i, j, n] 则是从i 到j 的最短路径的长度。 对于任意的k>0,通过分析可以得到:中间顶点不超过k 的i 到j 的最短路径有两种可能:该路径含或不含中间顶点k。若不含,则该路径长度应为c[i, j, k-1],否则长度为 c[i, k, k-1] +c [k, j, k-1]。c[i, j, k]可取两者中的最小值。 状态转移方程:c[i, j, k]=min{c[i, j, k-1], c [i, k, k-1]+c [k, j, k-1]},k>0。 这样,问题便具有了最优子结构性质,可以用动态规划方法来求解。
为了进一步理解,观察上面这个有向图:若k=0, 1, 2, 3,则c[1,3,k]= +∞;c[1,3,4]= 28;若k = 5, 6, 7,则c [1,3,k] = 10;若k=8, 9, 10,则c[1,3,k] = 9。因此1到3的最短路径长度为9。 下面通过程序来分析这一DP过程,对应上面给出的有向图:
#include <iostream>
using namespace std; const int INF = ;
int n=,map[][],dist[][][];
void init()
{
int i,j;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
map[i][j]=(i==j)?:INF;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
}
void floyd_dp()
{
int i,j,k;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
dist[i][j][]=map[i][j];
for(k=;k<=n;k++)
for(i=;i<=n;i++)
for(j=;j<=n;j++){
dist[i][j][k]=dist[i][j][k-];
if(dist[i][k][k-]+dist[k][j][k-]<dist[i][j][k])
dist[i][j][k]=dist[i][k][k-]+dist[k][j][k-];
}
}
int main()
{
int k,u,v;
init();
floyd_dp();
while(cin>>u>>v,u||v)
{
for(k=;k<=n;k++)
{
if(dist[u][v][k]==INF) cout<<"+∞"<<endl;
else cout<<dist[u][v][k]<<endl;
}
}
return ;
}
Floyd-Warshall算法不仅能求出任意2点间的最短路径,还可以保存最短路径上经过的节点。下面用精简版的Floyd算法实现这一过程,程序中的图依然对应上面的有向图。
#include <iostream>
using namespace std; const int INF = ;
int n=,path[][],dist[][],map[][];
void init(){
int i,j;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
map[i][j]=(i==j)?:INF;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
map[][]=,map[][]=,map[][]=;
}
void floyd(){
int i,j,k;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
dist[i][j]=map[i][j],path[i][j]=;
for(k=;k<=n;k++)
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if(dist[i][k]+dist[k][j]<dist[i][j])
dist[i][j]=dist[i][k]+dist[k][j],path[i][j]=k;
}
void output(int i,int j){
if(i==j) return;
if(path[i][j]==) cout<<j<<' ';
else{
output(i,path[i][j]);
output(path[i][j],j);
}
}
int main(){
int u,v;
init();
floyd();
while(cin>>u>>v,u||v){
if(dist[u][v]==INF) cout<<"No path"<<endl;
else{
cout<<u<<' ';
output(u,v);
cout<<endl;
}
}
return ;
}
输入 1 3
输出 1 2 5 8 6 3
最短路径——Floyd-Warshall算法的更多相关文章
- Floyd—Warshall算法
我们用DP来求解任意两点间的最短路问题 首先定义状态:d[k][i][k]表示使用顶点1~k,i,j的情况下,i到j的最短路径 (d[0][i][j]表示只使用i和j,因此d[0][i][j] = c ...
- 图论之最短路径(1)——Floyd Warshall & Dijkstra算法
开始图论学习的第二部分:最短路径. 由于知识储备还不充足,暂时不使用邻接表的方法来计算. 最短路径主要分为两部分:多源最短路径和单源最短路径问题 多源最短路径: 介绍最简单的Floyd Warshal ...
- 单源最短路径——Floyd算法
正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3). Floyd算法的基本思想如下:从任意 ...
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- 7-8 哈利·波特的考试(25 分)(图的最短路径Floyd算法)
7-8 哈利·波特的考试(25 分) 哈利·波特要考试了,他需要你的帮助.这门课学的是用魔咒将一种动物变成另一种动物的本事.例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等.反方向变 ...
- 最短路径问题---Dijkstra算法详解
侵删https://blog.csdn.net/qq_35644234/article/details/60870719 前言 Nobody can go back and start a new b ...
- Gym 101873D - Pants On Fire - [warshall算法求传递闭包]
题目链接:http://codeforces.com/gym/101873/problem/D 题意: 给出 $n$ 个事实,表述为 "XXX are worse than YYY" ...
- 数据结构与算法--最短路径之Bellman算法、SPFA算法
数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...
- 单源最短路径(dijkstra算法)php实现
做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...
- 最大流算法之EK(最短路径增广算法)
这是网络流最基础的部分--求出源点到汇点的最大流(Max-Flow). 最大流的算法有比较多,本次介绍的是其中复杂度较高,但是比较好写的EK算法.(不涉及分层,纯粹靠BFS找汇点及回溯找最小流量得到最 ...
随机推荐
- 测试框架Mocha与断言expect
测试框架Mocha与断言expect在浏览器和Node环境都可以使用除了Mocha以外,类似的测试框架还有Jasmine.Karma.Tape等,也很值得学习. 整个项目源代码: 为什么学习测试代码? ...
- div非弹出框半透明遮罩实现全屏幕遮盖css实现
IE浏览器下设置元素css背景为透明: background-color: rgb(0, 0, 0); filter: alpha(opacity=20); 非IE浏览器下设置元素css背景为透明: ...
- SQL Server 错误日志过滤(ERRORLOG)
一.背景 有一天我发现SQL Server服务器的错误日志中包括非常多关于sa用户的登陆错误信息:“Login failed for user 'sa'. 原因: 评估密码时出错.[客户端: XX.X ...
- jQuery源码分析系列(30) : Ajax 整体结构
开头引用一段 想起一句话:前端研究,研究个屁~ 的确如此呀.补充下联:前端设计,设计个屁~ 前端目前最大的困境是,如 HTML 一样,无论你承不承认,市场上并不太需要 HTML 高手 其实这里引发一个 ...
- Android之线程池深度剖析
1.线程池的引入 引入的好处: 1)提升性能.创建和消耗对象费时费CPU资源 2)防止内存过度消耗.控制活动线程的数量,防止并发线程过多. 使用条件: 假设在一台服务器完成一 ...
- MVC4做网站Demo进行重写的问题。
自从学习MVC4开始,边学边写这个demo,写了也有一年多了.开始觉得是一个小例子把所有的代码都写在一个项目中,边写边改越写越混乱,越到后来很多东西自己都理不清了.后来在群里跟 @怒放 在讨论这个问题 ...
- Android 在Service中弹出对话框
1.在Androidmanifest.xml中插入 <uses-permission android:name="android.permission.SYSTEM_ALERT_WIN ...
- 1Z0-053 争议题目解析685
1Z0-053 争议题目解析685 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 685.In your test database: -You are using Recover ...
- 重温Servlet学习笔记--session对象
session的类型是属于HttpSession,HttpSession是由javaWeb提供的,用来会话跟踪的类.session是服务器端对象,保存在服务器端. HttpSession是servle ...
- js实现动画效果框架
RT,是参照慕课的教程做的.两个多小时的教程,看完了然后晚上的时候做了下,看的时候感觉明白了,但其实做的时候还是有很多小细节需要处理的. 上代码,思想什么的直接去慕课看教程就好了.点击这里 注释也比较 ...