ワーシャルフロイド法というのを使うと、グラフのすべての2頂点間の最短路を求められるらしい。蟻本を参考にして解いてみた。
コードは以下。
#include <cstdio> #include <algorithm> #define REP(i,n) for(int i = 0; i < (int)(n); ++i) using namespace std; const int MAX_V = 200; int d[MAX_V][MAX_V]; void setCost(int d[MAX_V][MAX_V], int s, int e, int cost){ d[s][e] = d[e][s] = cost; } int main(){ // 頂点の数 const int V = 9; // 十分大きい数をとる const int INF = 1e4; // 辺のコストを初期化 // i = jのときは0とする // 辺が存在しないときはINFとする REP(i, V){ REP(j, V){ if (i == j) d[i][j] = 0; else d[i][j] = INF; } } // 辺のコストを設定 // (d, 0, 1, 2)は頂点0と頂点1の間のコストを2と設定するという意味 setCost(d, 0, 1, 2); setCost(d, 0, 2, 5); setCost(d, 1, 3, 3); setCost(d, 1, 4, 1); setCost(d, 2, 4, 4); setCost(d, 2, 6, 1); setCost(d, 3, 4, 2); setCost(d, 3, 5, 8); setCost(d, 4, 5, 9); setCost(d, 4, 6, 2); setCost(d, 7, 8, 5); // Warshall Floyd REP(k, V){ REP(i, V){ REP(j, V){ d[i][j] = min(d[i][j], d[i][k] + d[k][j]); } } } // 結果の表示 REP(i, V){ REP(j, V){ printf("%5d ", d[i][j]); } printf("\n"); } return 0; }
結果は以下。各頂点間の最短距離を行列で表示している。頂点7と8とは離れ小島になっているので、その他の頂点との最短距離はINFとなっていることが分かる。
0 2 5 5 3 12 5 10000 10000 2 0 4 3 1 10 3 10000 10000 5 4 0 5 3 12 1 10000 10000 5 3 5 0 2 8 4 10000 10000 3 1 3 2 0 9 2 10000 10000 12 10 12 8 9 0 11 10000 10000 5 3 1 4 2 11 0 10000 10000 10000 10000 10000 10000 10000 10000 10000 0 5 10000 10000 10000 10000 10000 10000 10000 5 0
参考
- プログラミングコンテストチャレンジブック
- TopCoder SRM 584 Div1 easy
- d[i][i]を0に初期化し忘れた人が失敗するケースが目立った回だった