1.弗洛伊德算法(Floyd)
弗洛伊算法核心就是三重循环,M [ j ] [ k ] 表示从 j 到 k 的路径,而 i 表示当前 j 到 k 可以借助的点;红色部分表示,如果 j 到 i ,i 到 k 是通的,就将 j 到 k 的值更新为
M[j][i] + M[i][k] 和 M[j][k] 较短的一个。
const int inf = 1<<30; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { for (int k = 1; k <= n; k++) { if (j!=k) { M[j][k] = min(M[j][i] + M[i][k] , M[j][k]); } } } }
给个题目链接,写完可以交试一下:http://www.dotcpp.com/oj/problem1709.html
完整代码:
#include <iostream> #include <queue> using namespace std; #define inf 2147483647 int M[1000][1000]; int main() { int n; queue<int>q; cin >> n; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { cin >> M[i][j]; if (M[i][j] == 0 && i != j)M[i][j] = inf; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { for (int k = 1; k <= n; k++) { if (M[j][k] != 0) { if (M[j][i] != inf && M[i][k] != inf) { M[j][k] = M[j][i] + M[i][k] < M[j][k] ? M[j][i] + M[i][k] : M[j][k]; } } } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (M[i][j] == inf)cout << -1 << " "; else cout << M[i][j] << " "; } cout << endl; } return 0; }View Code
2.迪杰斯特拉
Floyd只要暴力的三个for就可以出来,代码很好理解,但缺点就是时间复杂度高是O(n³)。Dijkstra的时间复杂度是O(n²),要快很多。
不过要注意这个算法所求的是单源最短路,啥意思呢,就是你得告诉我从哪个点出发,然后我能告诉你,从这个点到别的所有点的最短路径;
所以说,如果题目是求任意一对顶点间的最短路径问题,那就需要对每个顶点进行一遍迪杰斯特拉算法,这种情况就适合弗洛伊德算法了。
注意:
- 自己到自己的路径长度 0,到不了的点是 inf
-
inf 不能设置为 INT_MAX,这句话后边加出来就变成负的了。所以设置成了1<<30。
dis[i] = min(dis[i], dis[v] + M[v][i]);
测试题目:http://acm.hdu.edu.cn/showproblem.php?pid=2544
#include <iostream> #include <algorithm> #include <string.h> using namespace std; const int inf = 1 << 30; int n, m; bool book[1001]; int M[1001][1001]; int dis[1001]; void initialize() { memset(book, 0, sizeof(book)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i != j)M[i][j] = inf; } } for (int i = 1; i <= n; i++) { if (i != 1) dis[i] = inf; } } void dijkstra(){ while (true) { int v = 0; for (int i = 1; i <= n; i++) { if (!book[i] && (v == 0 || dis[i] < dis[v])) v = i;//从dis数组中找出当前距离起点最短的节点 } if (v == 0) break; book[v] = true; for (int i = 1; i <= n; i++) { dis[i] = min(dis[i], dis[v] + M[v][i]); } } } int main() { while (cin >> n >> m) { if (n == 0 && m == 0)break; initialize(); for (int i = 0; i < m; i++) { int A, B, C; cin >> A >> B >> C; M[A][B] = C; M[B][A] = C; } dijkstra(); cout << dis[n] << endl; } return 0; }