最大流入门 之 poj 1273
// [5/7/2014 Sjm]
/*
图论之最大流:
Ford-Fulkerson方法 dfs 实现
第一次接触网络流的题目,卡了好久。。。最后终于理解了代码,自己能敲出来了。。。
教训: (体会了算法的思想 != 能写出好的代码) => 要 知行合一
对代码细节理解(需要理解的关键位置):
1)对于 void Add_edge(int from, int to, int cap) 函数:
在构建出 s->t 的正向边后,立即构建 t->s 的反向边(容量为0)
2)dfs 回朔时,正向边与反向边容量变化。
*/
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <vector> 6 #include <algorithm> 7 using namespace std; 8 9 const int MAX_M = 200, INF = 0x3f3f3f3f; 10 struct edge { int to, cap, rev; }; 11 // 边 {终点, 容量, 反向边} 12 vector<edge> G[MAX_M]; // 邻接表构图 13 bool used[MAX_M]; // 用于 dfs 时判断点是否被访问过。 14 15 // 增加一条 16 void Add_edge(int from, int to, int cap) { 17 edge e1 = { to, cap, G[to].size() }; 18 G[from].push_back(e1); 19 // 增加 from -> to 的正向边 20 edge e2 = { from, 0, G[from].size() - 1 }; 21 // 增加 to -> from 的反向边 22 G[to].push_back(e2); 23 } 24 25 int Dfs(int v, int t, int f) { 26 if (v == t) return f; 27 used[v] = true; 28 for (int i = 0; i < G[v].size(); i++) { 29 edge &e = G[v][i]; 30 if (!used[e.to] && e.cap > 0) { 31 int d = Dfs(e.to, t, min(f, e.cap)); 32 if (d > 0) { 33 e.cap -= d; 34 // 增流后,正向边容量减少 d 35 G[e.to][e.rev].cap += d; 36 // 增流后,反向边容量增加 d 37 return d; 38 } 39 } 40 } 41 return 0; 42 } 43 44 int Max_flow(int s, int t) { 45 int max_flow = 0; 46 for (;;) { 47 memset(used, 0, sizeof(used)); 48 int f = Dfs(s, t, INF); 49 if (!f) return max_flow; 50 max_flow += f; 51 } 52 } 53 54 int main() 55 { 56 //freopen("input.txt", "r", stdin); 57 //freopen("output.txt", "w", stdout); 58 int n, m; 59 while (~scanf("%d %d", &n, &m)) 60 { 61 for (int i = 0; i < n; i++) { 62 int from, to, flow; 63 scanf("%d %d %d", &from, &to, &flow); 64 Add_edge(from - 1, to - 1, flow); 65 } 66 printf("%d\n", Max_flow(0, m - 1)); 67 for (int i = 0; i < m; i++) { 68 G[i].clear(); 69 } 70 } 71 return 0; 72 }