算法 | Floyd-Warshall 算法
解决赋权图的多源最短路径问题:Floyd-Warshall 算法
- 能解决负边
- 不能解决负环
Floyd-Warshall 算法
复杂度
时间复杂度:$O(\left|V\right|^3)$
$\left|V\right|$ 为顶点数
分析
Floyd 算法比较简单,即暴力枚举了所有可能,从而找到任意两点的距离。
从点 $i$ 到点 $j$ 的走法无非两种:
- $i\rightarrow j$
- $i\rightarrow k\rightarrow j$
那么三个循环,遍历所有的 $i,j,k$,如果 $i\rightarrow k\rightarrow j$ 距离比 $i\rightarrow j$ 短,那么就更新距离。
防止无穷大溢出
数学中 $\infty+\infty=\infty$,但程序中两个代表 $\infty$ 的大数相加肯定是会溢出成负数的,这会对该松弛操作产生巨大的干扰。因此进行松弛操作时需要判断两数是否为 $\infty$,只要有一个数为 $\infty$,就跳过这次松弛操作以防溢出。
代码实现
const int MAXN = 1010, INF = 0x3f3f3f3f;
int e, v; // e边数 v顶点数
int dist[MAXN][MAXN]; // dist[x][y]代表x到y的距离
void floyd_init(void)
{
memset(dist, 0x3f, sizeof(dist));
for (int i = 1; i <= v; i++)
dist[i][i] = 0;
}
void floyd(void)
{
for (int k = 1; k <= v; k++)
for (int i = 1; i <= v; i++)
for (int j = 1; j <= v; j++)
if (dist[i][k] < INF && dist[k][j] < INF)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi