(任意两点间最短路)Floyd-Warshall算法

Floyd-Warshall算法使用DP方法来求解任意两点间的最短路问题。
i到j的最短路分正好经过顶点k一次和完全不经过顶点k两种情况来讨论。不断的进行d[i][j] = min(d[i][j], d[i][k] + d[k][j])的更新来实现,复杂度是O(n ^ 3)。
此算法可以处理负权边,也可以判断图中是否有负圈,只需检查是否存在d[i][i]是负数的顶点i就可以了。

//Floyd-Warshall
#include 
#include 
#include 
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("有负圈\n");
    }
    return 0;
}

你可能感兴趣的:((任意两点间最短路)Floyd-Warshall算法)