1.Floyd-Warshall 算法

给定一张图,在o(n3)时间内求出任意两点间的最小距离,并可以在求解过程中保存路径

2.Floyd-Warshall 算法概念

这是一个动态规划的算法。

将顶点编号,假设依次为0,1,2…n-1,现在假设DP[i][j][k]表示从i出发,结束于j的满足经过结点的编号至多为k的最短路径,由此性质易知,在易知DP[i][j][k]时,若要求DP[i][j][k+1],有两种情况要考虑:

  1. DP[i][j][k+1]所表征的路径经过结点k+1,此时DP[i][j][k+1] = DP[i][k+1][k] + DP[k+1][j][k]
  2. DP[i][j][k+1]所表征的路径不经过结点k+1,此时DP[i][j][k+1] = DP[i][j][k],不用更新表项

属于哪种情况只需进行一次比较选择较小的即可,当第n-1轮循环结束,表项中的值DP[i][j]就代表了顶点i , j之间的最短距离,由算法的描述易知,时间复杂度必然是O(N3),但是空间复杂度可以通过复用DP数组减少到O(N2),这是为什么呢?如何保存路径?

分析1:要证明DP数组只需两维,只需证明第k+1轮循环中DP数组前面被改动的部分不会被用到即可且用到的一定没有被改动即可。假设第i论循环中dp[i][j]及之前的dp数组项已经被计算出来,接下来的运算中dp[inext][jnext],需要计算上面两种情况下的值:

  • 对于第1种情况,DP[inext][jnext][k+1] = DP[inext][k+1][k] + DP[k+1][jnext][k],对于DP[inext][k+1][k],如果它在本轮循环被更新,那么它实际上可以被标识为DP[inext][k+1][k+1],这就是一个矛盾,第k+1个点已经作为端点存在,却又说k+1个顶点可能在路径中存在。所以它不可能在本轮被更新,即实际上它还是DP[inext][k+1][k],DP[k+1][jnext][k]的分析相同,见下面的分析2.
  • 对第2种情况,DP[inext][jnext][k+1] = DP[inext][jnext][k] , 要么inext>i,要么inext==i&&jnext>j,即DP[inext][jnext]之前肯定未被更新,不存在问题。

分析2:一个令人迷惑的问题就是在第k+1轮循环计算DP[i][k+1](DP[k+1][j]的分析相同),按照上面两种情况分类 ,二者相等, 可以知道的确是不用更新的

  • 对第一种情况:DP[i][k+1][k+1] = DP[i][k+1][k] + DP[k+1][k+1][k] = DP[i][k+1][k]
  • 对第二种情况:DP[i][k+1][k+1] = DP[i][k+1][k]

分析3:初始状况的分析,初始状况相当于不经过任何结点,对于任意两个顶点 i , j ,自然有

  • 若 i , j 之间有边相连,则 DP[i][j] = cost(i,j)
  • 反之 ,DP[i][j] = INF

分析4 : 如何记录路径,设path[i][j]表示 i  到 j 的最短路径中 i 的后继顶点,初始情况下,若i ,j 之间有边相连,path[i][j] = j ,否则,path[i][j] = –1,在不断收敛的过程中,若当前最短路径有变化,path[i][j] = path[i][k+1]

 

3.代码

头文件:

/*
areslipan@163.com
filename : Floyd_Warshall.h
*/
#ifndef _FLOYD_WARSHALL_
#define _FLOYD_WARSHALL_
#include "graph.h" using namespace std; void Floyd_Warshall(Graph_Matrix & g,Graph_Matrix &path,Graph_Matrix &dp);
void Floyd_Warshall_Path(Graph_Matrix &path, int start, int end); #endif

实现文件:


/*
areslipan@163.com
filename : Floyd_Warshall.cpp
*/ #include "Floyd_Warshall.h" using namespace std; void Floyd_Warshall(Graph_Matrix & g,Graph_Matrix &path,Graph_Matrix &dp)
{
//可以先用Bellman-Ford算法检查一下是否有负值回路 int numNodes=g.size(); //图用矩阵表示,因此为了方便起见path和dp表也按照图的方式存放
path=g;
dp=g; for(int i=0;i<numNodes;++i)
{
for(int j=0;j<numNodes;++j)
{
if(g[i][j]>=MYINF)path[i][j] = -1 ;//-1 表示不经过任何结点
else path[i][j] = j;
dp[i][j]=g[i][j];
}
} for(int k=0;k<numNodes;++k)
for(int i=0;i<numNodes;++i)
for(int j=0;j<numNodes;++j)
{
if(dp[i][k]<MYINF && dp[k][j]<MYINF && dp[i][k]+dp[k][j]<dp[i][j])
{
dp[i][j] = dp[i][k] + dp[k][j];
path[i][j] = path[i][k];//path[i][j]存储i到j的路线上i的后继结点
}
} }
void Floyd_Warshall_Path(Graph_Matrix &path, int start, int end)
{ cout<<"从"<<start<<"到"<< end <<"的最短路径 : "; while(start!=end)
{
cout<<start<<" ";
start=path[start][end];
if(start==-1)
{
cout<<"no route!!"<<endl;return;
}
}
cout<<end<<endl;
}

 

 

测试文件:

/*
areslipan@163.com
filename : testFloydWarshall.cpp
*/ #include "Floyd_Warshall.h" using namespace std; int main()
{
vector<vector<int> > g;
create_an_graph_from_stdin(g,6);
vector<vector<int> >path;
vector<vector<int> >dp; cout<<"The minimun distance is "<<Floyd_Warshall(g,path,dp)<<endl; while(true)
{
int start;
int end;
cout<<"输入要查询的起点和终点:"<<endl;
cin>>start>>end;
Floyd_Warshall_Path(path,start,end);
}
system("pause");
}

 

测试用例:

1000 表示无穷大

0 1 4 1000 1000 1000
1 0 2 7 5 1000
4 2 0 1000 1 1000
1000 7 1000 0 3 2
1000 5 1 3 0 6
1000 1000 1000 2 6 0

 

算法结果:

图算法之Floyd-Warshall 算法-- 任意两点间最小距离的更多相关文章

  1. AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)

    题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...

  2. 【算法】Floyd-Warshall算法(任意两点间的最短路问题)(判断负圈)

    求解所有两点间的最短路问题叫做任意两点间的最短路问题. 可以用动态规划来解决, d[k][i][j] 表示只用前k个顶点和顶点i到顶点j的最短路径长度. 分两种情况讨论: 1.经过顶点k,  d[k] ...

  3. 任意两点间的最短路问题(Floyd-Warshall算法)

    /* 任意两点间的最短路问题(Floyd-Warshall算法) */ import java.util.Scanner; public class Main { //图的顶点数,总边数 static ...

  4. Floyd—Warshall算法

    我们用DP来求解任意两点间的最短路问题 首先定义状态:d[k][i][k]表示使用顶点1~k,i,j的情况下,i到j的最短路径 (d[0][i][j]表示只使用i和j,因此d[0][i][j] = c ...

  5. LCA - 求任意两点间的距离

    There are n houses in the village and some bidirectional roads connecting them. Every day peole alwa ...

  6. 任意两点间最短距离floyd-warshall ---- POJ 2139 Six Degrees of Cowvin Bacon

    floyd-warshall算法 通过dp思想 求任意两点之间最短距离 重复利用数组实现方式dist[i][j] i - j的最短距离 for(int k = 1; k <= N; k++) f ...

  7. Floyed-Warshall算法(求任意两点间最短距离)

    思路:感觉有点像暴力啊,反正我是觉得很暴力,比如求d[i][j],用这个方法求的话,就直接考虑会不会经过点k(k是任意一点) ,最终求得最小值 看代码 #include<iostream> ...

  8. Dijkstra算法:任意两点间的最短路问题 路径还原

    #define _CRT_SECURE_NO_WARNINGS /* 7 10 0 1 5 0 2 2 1 2 4 1 3 2 2 3 6 2 4 10 3 5 1 4 5 3 4 6 5 5 6 9 ...

  9. 任意两点间的最短路问题(Floyd-Warshall算法)

    #define _CRT_SECURE_NO_WARNINGS /* 7 10 0 1 5 0 2 2 1 2 4 1 3 2 2 3 6 2 4 10 3 5 1 4 5 3 4 6 5 5 6 9 ...

随机推荐

  1. NandFlash详述【转】

    NandFlash详述 转自:http://wenku.baidu.com/view/04d9330bb52acfc789ebc92f.html?re=view 1. 硬件特性: [Flash的硬件实 ...

  2. SQL分组查询group by

    注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里. 1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用 group ...

  3. [2014-03-13 08:46:42 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.

    Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace. 问题提示 ...

  4. 如何给桌面搬家(Win XP)

    是不是习惯把一些常用的文件放在桌面上?或者接收个文件就直接放桌面了,这样用起来方便点. 可是一旦你重装系统或者恢复系统,桌面又回到了以前的状态,很多的文件就丢了.小心的话,重做系统前会做个备份.但如果 ...

  5. Java 数据类型转换

    int iValue = new Integer(strValue).intValue();String str = intObj.toString();int number = Integer.pa ...

  6. phpcms上线步骤,无法生成缓存,页面空白原因

    缓存目录没有设置成777. 1.修改数据库配置 2.修改数据表中的本地地址成线上地址 3.修改代码中的配置,本地地址批量改为线上地址 4.登录后台,更新缓存

  7. 纠结和郁闷的存在感-关于DirectX与HLSL的矩阵存储方式---转载好文章

    我常常这么大胆的认为,搞科学的人总是喜欢用各种让常人难以理解的复杂方式去处理某些其实可能很简单的事情,这种情况在他自身擅长的.有着诸多对手竞争的领域上极为常见.比如吧,搞DirectX的人用了左手坐标 ...

  8. 设置Sublime Text2 中代码提示

    打开sublime text的菜单 Preferences -> Package Settings -> GoSublime ->Settings – User  然后输入 { &q ...

  9. core--线程同步(用户模式)

    用户模式下的多线程同步只适用用于同一个进程内的多个线程,其范围使用于读写问题:比如一本书,必须是作者A写完之后,读者B才能够读取.否则作者一边修改,读者一边读,完全乱套. 线程读者B如何能在多线程环境 ...

  10. MVC简捷调用EasyUI的datagrid

    一直想在项目中使用EasyUi的datagrid,但种种原因,没有实现. 这两天在开发一个项目中,愿望终于得以实现. 先看效果: 实现步骤是这样的: 1,在页面中画dataGrid,具体代码如下: & ...