Edmonds-Karp算法求解最大流(POJ 1273)
分析:经典的最大流问题,这里我们采用Edmonds-Karp算法(复杂度为$O(m^{2}n)$). 核心操作为BFS以及残差网络$G_{f}$的更新。对于BFS,为了得到$O(m)$的复杂度,采用邻接表。为了得到augmenting path之后更新$G_{f}$更加高效,我们为每条边编号。每条边$(u,v)$包括到达的结点$v$, 容量$cap$, 以及与该条边有同起点的边的编号。例如:从$u$出发有三条边$(u,v_{1})$, $(u,v_{2})$, $(u,v_{3})$, 三条边对应的编号分别为$t_{1}, t_{2}, t_{3}$, 令
$nex[t_{1}]=head[u]$;
$head[u]=t_{1}$;
$nex[t_{2}]=head[u]$;
$head[u]=t_{2}$;
$nex[t_{3}]=head[u]$;
$head[u]=t_{3}$;
我们可以得到
$nex[t_{1}]=head[u]$;
$nex[t_{2}]=t_{1}$;
$nex[t_{3}]=t_{2}$;
$head[u]=t_{3}$;
然后从$head[u]$我们可以得到$u$出发的边$t_{3}$, 然后通过$nex$可以得到$t_{2}$, $t_{1}$. 每条原始边的编号$i$为偶数(从$0$开始),对应的逆向边为$i$$^$$1$, 也即是$i+1$, 这样做的目的是在原始边和逆向边之间切换比较方便,$i$$^$$1=i+1$, $(i+1)$$^$$1=i$.
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 #include<string.h> 5 using namespace std; 6 int utoe[205];//结点u对应的边e的编号 7 int pres[205]; 8 int vist[205];//在BFS中判断每个结点是否被访问过 9 int minc[205]; 10 int s, t, maxflow; 11 int INF = 0x3f3f3f3f; 12 struct 13 { 14 int cap;//边的容量 15 int toVer;//边(u,v)对应的v 16 int nex;//边(u,v1)上一条共起点的边(u,v2)的编号 17 } edge[405]; 18 bool BFS() 19 { 20 int e_idx; 21 int top_ele; 22 int v; 23 queue<int>q;//STL不支持清空队列,所以每次BFS都定义一个新的队列 24 memset(vist, 0, sizeof(vist));//标记每个结点是否被访问: 0表示没有,1表示有 25 q.push(s); 26 vist[s] = 1; 27 minc[s] = INF; 28 while (!q.empty()) 29 { 30 top_ele = q.front(); 31 q.pop(); 32 e_idx = utoe[top_ele]; 33 while (e_idx >= 0) 34 { 35 if (edge[e_idx].cap > 0) 36 { 37 v = edge[e_idx].toVer; 38 if (vist[v]) 39 { 40 e_idx = edge[e_idx].nex; 41 continue; 42 } 43 vist[v] = 1; 44 minc[v] = min(minc[top_ele],edge[e_idx].cap); 45 q.push(v); 46 pres[v] = e_idx; 47 if (v == t) 48 return true; 49 } 50 e_idx = edge[e_idx].nex; 51 } 52 } 53 return false; 54 } 55 void Update() 56 { 57 int v = t; 58 int u; 59 while (v != s) 60 { 61 u = pres[v]; 62 edge[u].cap -= minc[t]; 63 edge[u^1].cap += minc[t]; 64 v = edge[u^1].toVer; 65 } 66 maxflow += minc[t]; 67 } 68 int main() 69 { 70 int m, n; 71 int u, v, c; 72 int i; 73 int id_e; 74 while (scanf("%d%d", &m, &n) == 2) 75 { 76 id_e = -1; 77 s = 1; 78 t = n; 79 memset(utoe, -1, sizeof(utoe)); 80 for (i = 1; i <= m; i++) 81 { 82 scanf("%d%d%d", &u, &v, &c); 83 edge[++id_e].cap = c; 84 edge[id_e].toVer = v; 85 edge[id_e].nex = utoe[u]; 86 utoe[u] = id_e; 87 88 edge[++id_e].cap = 0; 89 edge[id_e].toVer = u; 90 edge[id_e].nex = utoe[v]; 91 utoe[v] = id_e; 92 } 93 maxflow = 0; 94 while (BFS()) 95 Update(); 96 printf("%d\n", maxflow); 97 } 98 return 0; 99 }