実現したいこと
以下プログラムの変数「F」(70~73行目)について何を示しているのかを知りたいです。
解説によると「スタートからゴールまでの各辺の最小容量」との記載があったのですが、よくわからないです。
前提
以下、該当プログラムです。
入力データ
6 9 0 1 5 0 3 5 1 3 37 1 2 4 3 2 3 3 4 9 2 4 56 2 5 9 4 5 2
該当のソースコード
C++
1#include <iostream> 2#include <vector> 3using namespace std; 4 5// グラフを表す構造体 6struct Graph { 7 // 辺を表す構造体 8 // rev: 逆辺 (to, from) が G[to] の中で何番目の要素か 9 // cap: 辺 (from, to) の容量 10 struct Edge { 11 int rev, from, to, cap; 12 Edge(int r, int f, int t, int c) : 13 rev(r), from(f), to(t), cap(c) {} 14 }; 15 16 // 隣接リスト 17 vector<vector<Edge>> list; 18 19 // N: 頂点数 20 Graph(int N = 0) : list(N) { } 21 22 // グラフの頂点数取得 23 size_t size() { 24 return list.size(); 25 } 26 27 // Graph インスタンスを G として, 28 // G.list[v] を G[v] と書けるようにしておく 29 vector<Edge> &operator [] (int i) { 30 return list[i]; 31 } 32 33 // 辺 e = (u, v) の逆辺 (v, u) を取得する 34 Edge& redge(const Edge &e) { 35 return list[e.to][e.rev]; 36 } 37 void run_flow(Edge &e, int f) { 38 e.cap -= f; 39 redge(e).cap += f; 40 } 41 42 43 void addedge(int from, int to, int cap) { 44 //cout<<"From="<<from<<endl; 45 /*cout<<"To="<<to<<endl; 46 cout<<"Cap="<<cap<<endl;*/ 47 int fromrev = (int)list[from].size(); 48 //cout << "fromrev="<<fromrev<<endl; 49 int torev = (int)list[to].size(); 50 //cout << "torev="<<torev<<endl; 51 list[from].push_back(Edge(torev, from, to, cap)); 52 list[to].push_back(Edge(fromrev, to, from, 0)); 53 } 54}; 55 56struct FordFulkerson { 57 static const int INF = 1 << 30; 58 vector<int> seen; 59 60 FordFulkerson() { } 61 62 // 残余グラフ上で s-t パスを見つける (深さ優先探索) 63 // 返り値は s-t パス上の容量の最小値 (見つからなかったら 0) 64 // f: s から v へ到達した過程の各辺の容量の最小値 65 int fodfs(Graph &G, int v, int t, int f) { 66 cout<<"V="<<v<<endl; //スタート 67 cout<<"T="<<t<<endl; //ゴール 68 cout<<"F="<<f<<endl; 69 // 終端 t に到達したらリターン 70 if (v == t) return f; 71 72 // 深さ優先探索 73 seen[v] = true; 74 for (auto &e : G[v]) { 75 cout<<"Seen[e.to]="<<seen[e.to]<<endl; 76 if (seen[e.to]) continue; 77 78 79 cout<<"e.cap="<<e.cap<<endl; 80 if (e.cap == 0) continue; 81 82 83 int flow = fodfs(G, e.to, t, min(f, e.cap)); 84 cout << "Flow=" <<flow << endl; 85 86 // s-t パスが見つからなかったら次辺を試す 87 if (flow == 0) continue; 88 89 // 辺 e に容量 flow のフローを流す 90 G.run_flow(e, flow); 91 92 // s-t パスを見つけたらパス上最小容量を返す 93 return flow; 94 } 95 96 // s-t パスが見つからなかったことを示す 97 return 0; 98 } 99 100 // グラフ G の s-t 間の最大流量を求める 101 // ただしリターン時に G は残余グラフになる 102 int solve(Graph &G, int s, int t) { 103 int res = 0; 104 105 // 残余グラフに s-t パスがなくなるまで反復 106 while (true) { 107 seen.assign((int)G.size(), 0); 108 int flow = fodfs(G, s, t, INF); 109 110 // s-t パスが見つからなかったら終了 111 if (flow == 0) return res; 112 113 // 答えを加算 114 res += flow; 115 } 116 117 // no reach 118 return 0; 119 } 120}; 121 122int main() { 123 // グラフの入力 124 // N: 頂点数、M: 辺数 125 int N, M; 126 cin >> N >> M; 127 Graph G(N); 128 for (int i = 0; i < M; ++i) { 129 int u, v, c; 130 cin >> u >> v >> c; 131 132 // 容量 c の辺 (u, v) を張る 133 G.addedge(u, v, c); 134 } 135 136 // フォード・ファルカーソン法 137 FordFulkerson ff; 138 int s = 0, t = N - 1; 139 cout << ff.solve(G, s, t) << endl; 140}
試したこと
- 関係しそうな変数の出力(V,T)
➡Vが深さ優先の始点、Tが終点というのはわかりました。だが、Fの解決には結びつかず...。
- 深さ優先の際に使う変数の出力
➡Seen[e.to]やe.capもどういう役割かはわかりませんが、関係なさそう...。
出力(一部抜粋)
V=0 T=5 F=1073741824 Seen[e.to]=0 e.cap=5 V=1 T=5 F=5 Seen[e.to]=1 Seen[e.to]=0 e.cap=37 V=3 T=5 F=5 Seen[e.to]=1 Seen[e.to]=1 Seen[e.to]=0 e.cap=3 V=2 T=5 F=3 Seen[e.to]=1 Seen[e.to]=1 Seen[e.to]=0 e.cap=56 V=4 T=5 F=3 Seen[e.to]=1 Seen[e.to]=1 Seen[e.to]=0 e.cap=2 V=5 T=5 F=2 Flow=2 Flow=2 Flow=2 Flow=2 Flow=2
補足情報(FW/ツールのバージョンなど)
抽象的な疑問で申し訳ないですが、𠮟咤激励含めて些細なことでも構いませんので、よろしくお願いいたします。
※実行環境:Paiza

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。