<style> .blue { color: #38bdf8 } </style> # Maximum Flow ## Introduction ### Definition --- :::info #### ***Flow networks*** ::: A flow network $G = (\ V,\ E\ )$ is a directed graph in which each edge $(u,\ v) \in E$ has nonnegative capacity $c \ (u, \ v) \ge 0$ * $if \ (u, \ v) \in E \implies (v, u) \not\in E$ (not allow self-loops) * each network contains a source $s$ and a sink $t$ * $\forall \ v \in V$ always exists a path $s \rightarrow v \rightarrow t$ * $|\ E\ | \ge |\ V\ | - 1$ > each vertex other than $s$ has at least one entering edge > ![image](https://hackmd.io/_uploads/HkP3Z-UtR.png) > each eage is labeled by $f(u,v)/c(u,v)$ :::info ***Flow*** ::: A flow in $G$ is a real-valued function $f : V \times V \rightarrow \mathbb {R}$ > vetex之間有一實數代表flow (直觀理解) * **Capacity constraint** $\forall \ u, \ v \in V ,\ \ 0 \le f\ (u,\ v) \le c\ (u,\ v)$ > 點跟點之間flow不可能超過capacity * **Flow conservation** $\forall \ u \in V - \{s,\ t\}\ , \ \sum\limits_{v \ \in V} f\ (v,\ u)=\sum\limits_{v \ \in V} f\ (u,\ v)$ > 有多少水流流進 $u$ 就有多少水流從 $u$ 流出 * **The value of a flow** $|\ f\ | = \sum\limits_{v \ \in V} f\ (s, \ v) - \sum\limits_{v \ \in V} f\ (v, \ s)$ > $|\ f \ |$代表flow value,類似於向量長表示法 > the total flow out of the source minus the flow into the source :::warning maximun-flow problem 主要目標是最大化 $|\ f\ |$ ::: :::info ***Residual networks*** ::: Given a flow network $G=(V,\ E)$ and a flow $f$ , the residual network of $G$ induced by $f$ is $G_f = (V,\ E_f)$ , where $E_f = \{\ (u,\ v) \in V \times V: c_f(u, \ v) \gt 0\}$ Residual network consists of edges whose capacities represent how the flow can change on edges of $G$ . We define the <span class="blue">residual capacity</span> $c_f\ (u, \ v)$ by \begin{align} c_f\ (u, \ v) = \begin{cases} &c\ (u, \ v) - f \ (u, \ v) &if\ (u, \ v) \in E, \\ &f\ (v, \ u) &if \ (v,\ u) \in E, \\ &0 &otherwise \end{cases} \end{align} > 如果 (u, v) edge存在於 $G$,對應的意義是可<span class="blue">額外增加</span>多少流量 > 如果 (v, u) edge存在 $G$,對應的意義是可<span class="blue">撤回</span>多少流量 :::warning $(u, \ v) 、 (v, \ u)$不能同時存在,因為flow network的定義不允許雙向邊(self-loops) ::: :::warning $(v,\ u) \in E$,雖然$(u,\ v) \not\in E$ 不存在於 $G$,但其存在於$G_f$ (residual network)中,代表著<span class="blue">減少流量</span>,其目的是為了能夠撤銷$(v,\ u)$ flow,以便增加整體flow value ::: ![image](https://hackmd.io/_uploads/rkJndzLYR.png) > (a) represent the flow network and (b) represent the residual network of (a) ***property*** * $|\ E_f \ | \le 2\ |\ E\ |$ > residual network可表示flow network可增加或撤回的flow (最多2個edge),故residual edge一定不會超過flow networks edge 2 倍數量 :::info ***Augmentation*** ::: :::warning A flow in a residual network provides a roadmap for adding flow to the original flow network. ::: Let $f$ is a flow in $G$ , and $f^{\ '}$ is a flow in $G_f$ , we define $f \uparrow f{\ '}$ , the <span class="blue">augemntation</span> of flow $f$ by $f^{\ '}$, to be a function from $V \times V$ to $\mathbb {R}$ , defined by \begin{align} (f \uparrow f^{\ '}) (u,\ v) = \begin{cases} &f(u,\ v)+f^{\ '}(u, \ v)-f^{\ '}(v, \ u) &if\ (u,\ v)\in E \\ &0 &otherwise \end{cases} \end{align} > 這個式子表達了原本的flow增加與減少進行形成新的flow > 舉個例子,A $\rightarrow$ B 原本有5份水流,如今增加3份水流過去,同時又有2份水流過來 > 那麼現今A $\rightarrow$ B的flow也理所當然為 $5+3-2=6$ 份水流 :::warning Pushing flow on the reverse edge in the residual network is known as <span class="blue">cancellation</span> ::: ***Lemma 1*** Let $G = (V, \ E)$ be a flow network with source $s$ and sink $t$, and let $f$ be a flow in $G$. Let $G_f$ be the residual network of $G$ induced by $f$ , and let $f^{\ '}$ be a flow in $G_f$. Then the function $f \uparrow f^{\ '}$ is a flow in $G$ with value $|\ f \uparrow f^{\ '}\ |=|\ f\ |+|\ f^{\ '}\ |$ > 這個定理直觀的理解就是原本的flow $f$ 透過flow $f^{\ '}$作用形成新的flow $f \uparrow f^{\ '}$,而這個flow value為個別的flow value相加 :::info ***Augmenting paths*** ::: an <span class="blue">augmenting path</span> $p$ is a simple path from $s$ to $t$ in the residual network $G_f$ ![image](https://hackmd.io/_uploads/rkJndzLYR.png) > (b)圖中藍色的線就是augmenting path > 我們可以觀察到這段路徑可以通過最大容量為4 (取該路徑最小容量) :::warning 注意: 藍色路徑同時包含增加flow與撤回flow (對$G$而言) ::: We call the maximum amount by which we can increase the flow on each edge in an augmenting path $p$ the <span class="blue">residual capacity</span> of $p$ , given by $c_f(p)=min\{ c_f(u,\ v):(u,\ v)\ is\ in\ p \}$ ***Lemma 2*** Let $G = (V,\ E)$ be a flow network, let $f$ be a flow in $G$ , and let $p$ be an augmenting path in $G_f$. Define a function $f_p : V \times V \rightarrow \mathbb {R}$ by \begin{align} f_p(u,\ v) = \begin{cases} &c_f\ (p) &if\ (u,\ v)\ is\ on\ p \\ &0 &otherwise \end{cases} \end{align} Then, $f_p$ is a flow in $G_f$ with value $|\ f_p\ |=c_f\ (p) \gt 0$ > augmenting path $p$ 可以形成flow其值為該路徑的最小容量 ***Corollary 3*** By ***Lemaa 1*** and ***Lemaa 2*** , we can conclude $|\ f \uparrow f_{p}\ |=|\ f\ |+|\ f_{p}\ | \gt |\ f\ |$ :::info ***Cuts of flow networks*** ::: A <span class="blue">cut</span> $(S,\ T)$ of flow network $G=(V,\ E)$ is a partition of $V$ into $S$ and $T=V-S$ such that $s \in S$ and $t \in T$ ![image](https://hackmd.io/_uploads/ryiQn7PYR.png) if $f$ is a flow, then the <span class="blue">net flow</span> $f(S,\ T)$ across the cut $(S,\ T)$ is defined to be $f(S, T)=\sum\limits_{\ u\ \in S}\sum\limits_{\ v\ \in T}f(u,\ v)-\sum\limits_{\ u\ \in S}\sum\limits_{\ v\ \in T}f(v,\ u)$ > net flow的意義是從 $S$ 流向 $T$ 減去 $T$ 流向 $S$ 的flow,其計算方式就是將每個點跟點之間的流量加總 > 例如上圖,$f(v_1,\ v_3)+f(v_2,\ v_4)-f(v_3,\ v_2)=12+11-4=19$ The <span class="blue">capacity</span> of the cut $(S,\ T)$ is $c(S,\ T)=\sum\limits_{u \in S}\sum\limits_{v \in T} c(u,\ v)$ > capacity這裡只計算 $S$ 到 $T$ 的容量 >如上圖,$c(v_1,\ v_3)+c(v_2,\ v_4) = 12+14=26$ ***Lemma 4*** Let $f$ be a flow in a flow network $G$ with source $s$ and sink $t$ , and let $(S,\ T)$ be any cut of $G$. Then the net flow across $(S,\ T)$ is $f(S,\ T)=|\ f\ |$ ***Corollay 5*** The value of any flow $f$ in a flow network $G$ is bounded from above by the capacity of any cut of $G$ > 此推論描述,maximum flow一定不會超過任意cut的capacity --- ### Theorem :::info ***Max-flow min-cut theorem*** ::: if $f$ is a flow in a flow network $G=(V,\ E)$ with source $s$ and sink $t$, then the following conditions are equivalent: 1. $f$ is maximum flow in $G$ 2. $G_f$ contains no augmenting paths 3. $|\ f\ | = c(S,\ T)$ for some cut of $(S,\ T)$ of $G$ :::warning 透過這個定理我們可以得出只要$G_f$不存在augmenting path時,代表此時已完成到最大流計算 ::: --- ### Ford-Fulkerson algorithm :::info ***basic version*** ::: ![image](https://hackmd.io/_uploads/rJm-qEPKC.png) :::danger Ford-Fulkerson若使用DFS尋找augmenting path,使得worse case complexity為$O(|\ f\ | * E)$ ::: ![image](https://hackmd.io/_uploads/B1chSfcFA.png) > 如上圖所示,需要迭代2000000回才能得出答案 :::info ***The Edmonds-Karp algorithm*** ::: 為了避免worse case,The Edmonds-Karp algorithm採用BFS選擇路徑,亦即尋找shortest path $Time\ Complexity:\ O(VE^2)$ $Space\ Complexity:\ O(V)$ ```cpp= #include <iostream> #include <vector> #include <queue> #include <climits> using namespace std; struct Edge { int from; int to; int flow; int capacity; }; class Graph { private: int nv, ne, min; vector<vector<int>> graph; vector<vector<int>> residual; vector<int> paths; vector<Edge> edges; public: Graph(int nv = 0, int ne = 0): nv(nv), ne(ne) { graph.reserve(nv); residual.reserve(nv); paths.reserve(nv); int s, d, c; for (int i = 0; i < ne; i++) { cin >> s >> d >> c; edges.push_back({s, d, 0, c}); edges.push_back({d, s, 0, 0}); graph[s].push_back(edges.size()-2); residual[d].push_back(edges.size()-1); residual[s].push_back(edges.size()-2); } } bool findAugmenting() { // bfs queue<int> q; vector<bool> visited(nv, false); bool found = false; int now = 0; for (int& i : residual[now]) { if (edges[i].capacity > 0) q.push(i); } visited[now] = true; while (!q.empty()) { int i = q.front(); q.pop(); now = edges[i].to; visited[now] = true; paths[now] = i; if (now == nv-1) { found = true; break; } for (int& j : residual[now]) { if (edges[j].capacity > 0 && !visited[edges[j].to]) { q.push(j); } } } return found; } int fordFulkerson() { int v, flow = 0, index; while (findAugmenting()) { v = nv-1; min = INT_MAX; minCapacity(v); while (v) { index = paths[v]; Edge& e = edges[index]; if (index % 2 == 0) { // exist in origin graph e.capacity -= min; e.flow += min; // add backward edge edges[index+1].capacity = e.flow; } else { // cancelation edges[index-1].flow -= min; edges[index-1].capacity += min; // decrease bafckward edge capacity e.capacity = edges[index-1].flow; } v = e.from; } } for (int i : graph[0]) { flow += edges[i].flow; } return flow; } void minCapacity(int v) { if (!v) return; Edge& e = edges[paths[v]]; if (e.capacity < min) min = e.capacity; minCapacity(e.from); } void printPath(int v) { if (!v) return; Edge& e = edges[paths[v]]; printPath(e.from); cout << e.from << " " << e.to << " " << e.flow << " " << e.capacity << endl; } void printGraph() { for (int i = 0; i < nv; i++) { for (int j = 0; j < graph[i].size(); j++) { cout << edges[graph[i][j]].from << " " << edges[graph[i][j]].to << " " << edges[graph[i][j]].capacity << endl; } } } }; int main() { int nv, ne; cin >> nv >> ne; Graph g(nv, ne); cout << g.fordFulkerson() << endl; return 0; } ``` > input > 6 9 0 1 16 0 2 13 1 3 12 2 1 4 2 4 14 3 2 9 3 5 20 4 3 7 4 5 4 > output 23 --- ### Reference --- * Introduction to algorithms 4th edition >[name=Sky] ###### tags: `Algorithm`