TOP > グラフ 全点対間最短路 全点対間最短路(Warshall-Floyd) 2018/04/15 • ei1333 説明 隣接行列で表されるグラフの全点間最短路を求めるアルゴリズム。負辺があっても動作する。負閉路が存在する場合はそれも検出する(ある頂点 $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]); } } } } 検証 AOJ GRL_1_C 全点対間最短経路 #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'); } }