1 条题解
-
0
题意
本题要求理解并应用弗洛伊德(Floyd)算法的核心原理。题目中给出的是标准的弗洛伊德算法实现,通过三重循环逐步更新任意两点之间的最短路径。
思路
弗洛伊德算法的通用形式如下:
for (k = 1; k <= n; k++) for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) a[i][j] = min(a[i][j], a[i][k] + a[k][j]);即在每一步中,我们尝试通过顶点 来“中转”路径。
本题的思路不是删除顶点,而是逆向添加顶点(从后往前处理)。
在每一步中,我们尝试通过新加入的顶点,在所有顶点之间进行路径中转。
这样可以得到一个时间复杂度为 的解法。算法步骤
- 初始化距离矩阵 ,其中 表示顶点 到顶点 的当前最短距离。
- 按照逆向顺序(从最后一个顶点到第一个顶点)依次添加顶点。
- 每添加一个顶点 ,就使用该顶点作为中转点,更新所有顶点对 的距离:
- 重复步骤 3,直到所有顶点都被添加完毕。
复杂度分析
- 时间复杂度:,因为三重循环分别遍历所有顶点对和中转顶点。
- 空间复杂度:,用于存储距离矩阵。
代码说明
代码实现的核心是三重循环,其中外层循环 表示当前添加的顶点,内层循环 和 遍历所有顶点对。每次通过 进行松弛操作,更新最短路径。由于是逆向添加顶点,最终得到的结果与正向删除顶点等价。
#include <bits/stdc++.h> using namespace std; #define int long long int n; int dis[505][505]; int d[505]; int ansline[505],book[505]; signed main(){ cin >> n; for(int i = 1 ; i <= n ; i ++) for(int j = 1 ; j <= n ; j ++) cin >> dis[i][j]; for(int i = 1 ; i <= n ; i ++)cin >> d[i]; for(int v = n ; v >= 1 ; v --){ int x = d[v]; book[x] = 1; for (int i = 1 ; i <= n ; i ++) for (int j = 1 ; j <= n ; j ++) if(i != j){ //因为把当前加入的点x作为中转点,所以我们去掉了一重循环 dis[i][j] = min(dis[i][x] + dis[x][j],dis[i][j]);//x即是当前加入的点 if(book[i] != 0 && book[j] != 0)ansline[v] += dis[i][j]; } } for(int i = 1 ; i <= n ; i ++)cout << ansline[i] <<" "; return 0; }
- 1
信息
- ID
- 6722
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 7
- 已通过
- 1
- 上传者