多源最短路简介
多源最短路算法用于解决图中任意两节点间最短路径的问题,广泛应用于交通网络、社交关系分析、路由优化等场景。与单源最短路(如Dijkstra)不同,它一次性计算所有节点对的最短距离,适合需要全局路径规划的场景。
核心算法
Floyd算法:基于动态规划,通过三重循环松弛所有中间节点,时间复杂度为 O(V3)O(V^3)O(V3),适合稠密图或需要处理负权边的场景。其空间复杂度为 O(V2)O(V^2)O(V2),需存储所有节点对的距离矩阵。
Floyd算法:
Floyd算法本质是用动态规划,来求任意两个节点之间的最短路,也成为插点法。通过不断在两结点之间加入新的点,来更新最短路。且适用于任何图,不管有向无向,边权正负,但必须有最短路存在(也就是不存在负环)。
其实最本质上,就是分阶段,逐步更新出最终结果。
算法流程:
- 状态表示:f[k][i][j] 表示,仅仅通过 [1,k] 这些点,计算出结点 i 走到结点 j 的最短路径长度
- 状态转移方程:不选新来的点:
f[k][i][j] = f[k-1][i][j]
选择新来的点:f[k][i][j] = f[k-1][i][k] + f[k-1][k][j]
- 空间优化:只会用到上一层的状态,因此可以优化掉第一维。f[i][j]为初始状态下i到j的距离,如果没有边则为无穷
- 初始化:
f[i][j] = 0
- 填表顺序:一定要先枚举 k 再枚举 i 和 j。因为外面填表的时候需要依赖 k-1 曾的状态,因此,必须先枚举 k。
代码实现:
int main()
{cin >> n >> m;memset(f, 0x3f, sizeof f);for (int i = 1; i <= n; i++)f[i][i] = 0;for (int i = 1; i <= m; i++){int a, b, c; cin >> a >> b >> c;f[a][b] = f[b][a] = min(f[a][b], c);}//floydfor (int k = 1; k <= n; k++)//以那个点作为新的中间的桥梁节点(之前的点已经用过并保存在数组中,因此,k = n时使用的桥梁节点是前n个所有结点){for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){f[i][j] = min(f[i][j], f[i][k] + f[k][j]);}}}for (int i = 1; i <= n; i++){for(int j = 1; j <= n; j++)cout << f[i][j] << " ";cout << endl;}
}