Floyd-Warshall算法使用DP方法來求解任意兩點(diǎn)間的最短路問題。
i到j(luò)的最短路分正好經(jīng)過頂點(diǎn)k一次和完全不經(jīng)過頂點(diǎn)k兩種情況來討論。不斷的進(jìn)行d[i][j] = min(d[i][j], d[i][k] + d[k][j])的更新來實(shí)現(xiàn),復(fù)雜度是O(n ^ 3)。
此算法可以處理負(fù)權(quán)邊,也可以判斷圖中是否有負(fù)圈,只需檢查是否存在d[i][i]是負(fù)數(shù)的頂點(diǎn)i就可以了。
//Floyd-Warshall
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int
MAXV = 105, MAXE = 10005, INF = 0x3f3f3f3f;
int v, e;
int d[MAXV][MAXV];
bool Floyd_Warshall() {
for(int k = 1; k <= v; ++k) {
for(int i = 1; i <=v; ++i) {
for(int j = 1; j<= v; ++j) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
for(int i = 1; i <= v; ++i)
if(d[i][i] < 0)
return false;
return true;
}
int main() {
while(scanf("%d%d", &v, &e) != EOF && v && e) {
for(int i = 1; i <= v; ++i) {
for(int j = 1; j <= v; ++j) {
d[i][j] = d[j][i] = (i == j ? 0 : INF);
}
}
for(int i = 1; i <= e; ++i) {
int f, t, c;
scanf("%d%d%d",&f, &t, &c);
d[f][t] = d[t][f] = c;
}
if(Floyd_Warshall())
printf("%d\n", d[1][v]);
else
printf("有負(fù)圈\n");
}
return 0;
}