// [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
", Max_flow(0, m - 1));
67 for (int i = 0; i < m; i++) {
68 G[i].clear();
69 }
70 }
71 return 0;
72 }