TOP > グラフ 全点対間最短路
全点対間最短路(Warshall-Floyd)
説明
隣接行列で表されるグラフの全点間最短路を求めるアルゴリズム。負辺があっても動作する。負閉路が存在する場合はそれも検出する(ある頂点 $k$ から $k$ への最短路が負ならば負閉路が存在)。
計算量
- $O(V^3)$
実装例
- warshall_floyd($g$, $INF$):= 隣接行列 $g$ で表されるグラフの全点間最短路を求める。ここで到達できない要素には $INF$ が格納されている。
template< typename T >
void warshall_floyd(Matrix< T > &g, T INF) {
for(int k = 0; k < g.size(); k++) {
for(int i = 0; i < g.size(); i++) {
for(int j = 0; j < g.size(); j++) {
if(g[i][k] == INF || g[k][j] == INF) continue;
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
}
検証
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C"
#include "../../template/template.cpp"
#include "../template.cpp"
#include "../warshall-floyd.cpp"
int main() {
int V, E;
scanf("%d %d", &V, &E);
Matrix< int > mat(V, vector< int >(V, INT_MAX));
for(int i = 0; i < V; i++) mat[i][i] = 0;
for(int i = 0; i < E; i++) {
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
mat[x][y] = z;
}
warshall_floyd(mat, INT_MAX);
for(int i = 0; i < V; i++) {
if(mat[i][i] < 0) {
puts("NEGATIVE CYCLE");
return 0;
}
}
for(int i = 0; i < V; i++) {
for(int j = 0; j < V; j++) {
if(j > 0) putchar(' ');
if(mat[i][j] == INT_MAX) printf("INF");
else printf("%d", mat[i][j]);
}
putchar('\n');
}
}