Floyd-Warshall的适用范围
1、求所有节点对的最短路径
2、边的权重可以为负
3、不能存在负环路
Floyd-Warshall算法的描述
Floyd-Warshall实际上是一种动态规划的思想。假如图中有n个节点,编号为1~n,我们令d[k][i][j]表示只能使用1~k号节点作为中间节点时,节点i到j的最短路径距离。d[0][i][j]表示没有中间节点时,i到j的最短路径距离,d[1][i][j]表示只能有节点1作为中间节点时,i到j的最短路径长度。d[k][i][j]可以分为两种情况:
1、节点k在i到j的最短路径上,此时d[k][i][j]=d[k-1][i][k]+d[k-1][k][j]
2、节点k不在i到j的最短路径上,此时d[k][i][j]=d[k-1][i][j]
所以d[k][i][j]=min{d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]}
floyd的java模板
int n;//节点的总个数
int d[][][];//d[k][i][j]:能使用1~k号节点作为中间节点时,节点i到j的最短路径距离
int w[][];//w[i][j]:边(i,j)的权重,若i,j之间没有边,则令w[i][j]=MAX,若i==j,则w[i][j]=0
int MAX=0xfffff;//很大的一个数,用来表示两个节点之间没有边
void floyd()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
d[0][i][j]=w[i][j];
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
d[k][i][j]=Math.min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j]);
}
}
}
}
通过观察动态转移方程d[k][i][j]=min{d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]},我们可以发现k阶段的状态(d[k][i][j]),只与k-1阶段的转态(d[k-1]..)的状态有关,我们可以将上面的代码简化成
floyd简化版java模板
int n;//节点的总个数
int d[][];//d[i][j]:表示当前求得的i到j的最短路径距离
int w[][];//w[i][j]:边(i,j)的权重,若i,j之间没有边,则令w[i][j]=MAX,若i==j,则w[i][j]=0
int MAX=0xfffff;//很大的一个数,用来表示两个节点之间没有边
void floyd()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
d[i][j]=w[i][j];
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
if(d[i][j]>d[i][k]+d[k][j])
{
d[i][j]=d[i][k]+d[k][j];
}
}
}
}
}