1. 程式人生 > >Floyd-Warshall 所有結點對的最短路徑演算法

Floyd-Warshall 所有結點對的最短路徑演算法

以下程式碼僅支援結點是順序的,比如輸入5個結點,結點的編號只能是1到5,輸入順序可以不一致。

動態規劃真的簡潔,三個 for 把這麼複雜的東西就整理好了。
遞推公式:**d[i][j] = min ( d[i][j] , d[i][k] + d[k][j] ) **

動態規劃重點在於遞迴式:
不要看字,看這個圖!!!就很容易理解下面那個遞迴式了
在這裡插入圖片描述

在這裡插入圖片描述
維護了兩個矩陣,一個權重的矩陣(做計算)和一個前驅矩陣(輸出)

#include "stdafx.h"
#include <stdio.h>
#define inf 0x3f3f3f3f
#define N 100
int e[N][N],parent[
N][N]; int k, i, j; //迴圈變數 int n, m; //n是結點數,m是邊數 void Print_Shortest_Path(int i,int j) //遞迴輸出 { if (i == j) printf("%d ", i); else if (parent[i][j] == NULL) printf("no path \n"); else { Print_Shortest_Path(i, parent[i][j]); printf("%d ", j); } } void Floyd_Warshall() { for
(k = 1; k <= n; k++) { for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (e[i][j] > e[i][k] + e[k][j]) { e[i][j] = e[i][k] + e[k][j]; parent[i][j] = parent[k][j]; } } } } //輸出各點到各點的最小路徑 printf("\n最短路徑矩陣:\n"); for (i = 1; i <=n; i++) { for
(j = 1; j <= n; j++) { if (e[i][j] != inf) { printf("%5d ", e[i][j]); } } printf("\n"); } printf("\n前驅矩陣:\n"); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { printf("%5d ", parent[i][j]); } printf("\n"); } printf("\n結點間最短距離的情況:\n"); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { printf("%d --> %d : ", i, j); Print_Shortest_Path(i, j); printf("\n"); } printf("\n"); } } int main() { int t1, t2, t3; scanf_s("%d %d", &n, &m); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (i == j) //矩陣的對角線是0,自己到自己的距離是0 { e[i][j] = 0; parent[i][j] = NULL; } else { e[i][j] = inf; //表示不通達 parent[i][j] = i; } } } for (i = 1; i <= m; i++) { scanf_s("%d %d %d", &t1, &t2, &t3); e[t1][t2] = t3; //起點t1點到終點t2點的距離是t3 } Floyd_Warshall(); return 0; }

在這裡插入圖片描述