【算法-图论基础】最短路径-弗洛伊德算法
温馨提示:这篇文章已超过386天没有更新,请注意相关的内容是否还可用!
【算法-图论基础】最短路径-弗洛伊德算法
在生活中,我们往往会遇到这样的问题,从地点A到地点B,选择什么线路,选用哪几种交通工具的组合,花费的时间最少?
这个问题中,我们可以借助欧拉使用的数学工具——图论来研究,我们将每一个地点抽象为点,道路或者一个阶段的过程抽象为边,花费的时间就是边的权值。这样,问题就简化为在一个图中找两点之间的最短路径。
怎样解决这个问题呢,罗伯特·弗洛伊德给出了答案。
弗洛伊德算法采用动态规划的思想,假设我们要找的最短路径在点A与点B之间,那么,图中的所有点只有两种情况,要么在这条最短路径上(也就是中间点),要么不在这条最短路径上,我们可以根据这个来得出状态转移方程,依次将图中的每个点作为中间点遍历即可。
下面的题目来自蓝桥题库:
输入输出样例
输入:
3 3 3 1 2 1 1 3 5 2 3 2 1 2 1 3 2 3
输出:
1 3 2
按照题目意思我们可以得到下图:
此时,我们只考虑边权值为正。
在弗洛伊德算法中,我们采用邻接矩阵存图,因为这是天然的dp数组(两点之间无连接则值记为无穷大,方便找最小值),同时,为了能够得到最短路径我们用 f [ x ] [ y ] f[x][y] f[x][y]来记录从x到y的最短路径(保存y的前一个点)。
我们考虑图中的每一个点。
1、当点1作为中间点时(A->…->1->…->B)
更新两个数组, d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ i ] [ 1 ] + d p [ 1 ] [ j ] ) dp[i][j] = min(dp[i][j], dp[i][1] + dp[1][j]) dp[i][j]=min(dp[i][j],dp[i][1]+dp[1][j]) ,如果 d p [ i ] [ j ] = d p [ i ] [ 1 ] + d p [ 1 ] [ j ] dp[i][j]=dp[i][1]+dp[1][j] dp[i][j]=dp[i][1]+dp[1][j],对应 f [ i ] [ j ] = f [ 1 ] [ j ] f[i][j]=f[1][j] f[i][j]=f[1][j](注意只能取后半段)。
在本题的环境下,很显然,绿色部分是不用更新的,保留即可。
本轮不必更新,保留。
2、当点2作为中间点时(A->…->2->…->B)
黄色部分需要更新。
3、当点3作为中间点时(A->…->3->…->B)
本轮不必更新,保留。
遍历结束,得到最终结果。
再用查表的方法就能得到两点之间的最短路径值。
那么如何得到两点间的最短路径呢?
;利用f数组,我们知道A到B的最短路径中,B的前驱点是 f [ A ] [ B ] f[A][B] f[A][B],即 A − > . . . − > f [ A ] [ B ] − > B A->...->f[A][B]->B A−>...−>f[A][B]−>B,我们再将 f [ A ] [ B ] f[A][B] f[A][B]看作是 B B B,一直向前倒推即可。
AC代码放在下面:
#include
using namespace std;
#define int long long
const int N = 1e3 + 10;
const int INF = 0x3f3f3f3f3f3f3f3f;
int n, m, q;
int a[N][N];
void init() {
for (int i = 1; i
for (int j = 1; j
if (i != j) a[i][j] = INF;
}
}
return;
}
void floyd() {
for (int i = 1; i
for (int j = 1; j
if (j == i) continue;
for (int k = 1; k
if (k == j || k == i) continue; // 跳过对角线
if (a[j][k] a[j][i] + a[i][k]) {
a[j][k] = a[j][i] + a[i][k];
} // 更新最短路径长度及最短路径
}
}
}
return;
}
signed main() {
cin n m >> q;
init();
for (int i = 1; i
int from, to, value;
cin > from >> to >> value;
a[from][to] = a[to][from] = min(a[from][to],value);
} // 邻接矩阵存图
floyd();
while (q--) {
int f, t;
cin >> f >> t;
if(a[f][t] 






