|
| 1 | +--- |
| 2 | +tags: |
| 3 | + - OMSCS |
| 4 | + - Algorithms |
| 5 | + - Practice |
| 6 | +--- |
| 7 | +# 7.22 - Fast Max-Flow Recomputation |
| 8 | +> In a particular network $G=(V,E)$ whose edges have integer capacities $c_e$, we have already found the maximum flow $f$ from node $s$ to node $t$. However, we now find out that one of the capacity values we used was wrong: for edge $(u,v)$ we used $c_{uv}$ whereas it should have been $c_{uv}−1$. This is unfortunate because the flow $f$ uses that particular edge at full capacity: $f_{uv} = c_{uv}$. |
| 9 | +> |
| 10 | +> We could redo the flow computation from scratch, but there’s a faster way. Show how a new optimal flow can be computed in $O(|V|+ |E|)$ time. |
| 11 | +
|
| 12 | + |
| 13 | +## Exploration |
| 14 | +This is an extension of [[7.21 - Critical Edges]] which actually requires that we update the flows. We first need to check to see if that edge was critical. This can be done by reconstructing the residual network $G^f$ and then running DFS from $u$ in $G^f$ to see if $v$ is reachable. |
| 15 | + |
| 16 | +If $v$ is reachable from $u$ in $G^f$, we can use the results of DFS to update the flow. Starting from $v$, we can use $prev[]$ to retrace the steps back to $u$. This forms a uv-path in $G^f$. For each pair of vertices $a,b \in V$ encountered along the uv-path, we have an edge $e=(a,b)$ in the flow network. If the uv-path in $G^f$ traveled in the same direction of $e$ in $G$, we add 1 to $f_{ab}$. If the uv-path in $G^f$ traveled in the opposite direction of $e$ in $G$, we subtract 1 from $f_{ab}$. |
| 17 | + |
| 18 | +If $v$ is **not** reachable from $v$ in $G^f$, then edge $uv$ was a critical edge. This means that the overall flow through $G$ must be reduced by 1. In order to do this, we must find a us-path in $G^f$ via DFS (generating $prev_{us}$), and a tv-path in $G^f$ via DFS (generating $prev_{tv}$). For each of these paths, we must apply a similar procedure to the one above. |
| 19 | + |
| 20 | +- Starting from $s$, we can use $prev_{us}[]$ to retrace the steps "back" to $u$. Considering these vertices in reverse DFS order forms an su-path in $G^f$. For each pair of vertices $a,b \in V$ encountered along the su-path, we have an edge $e=(a,b)$ in the flow network. For each of these edges, we subtract 1 from $f_{ab}$. |
| 21 | +- Starting from $v$, we can use $prev_{tv}[]$ to retrace the steps "back" to $t$. Considering these vertices in reverse DFS order forms an vt-path in $G^f$. For each pair of vertices $a,b \in V$ encountered along the vt-path, we have an edge $e=(a,b)$ in the flow network. For each of these edges, we subtract 1 from $f_{ab}$. |
| 22 | + |
| 23 | +We finish off by making sure the original mistake was accounted for in $f$, by subtracting 1 from $f_{uv}$. |
| 24 | + |
| 25 | +## My Solution |
| 26 | +- Reconstruct the residual network $G^f$ from $f$, $G$, and $c$. |
| 27 | +- Run DFS from $u$ in $G^f$. We use $post[v]<post[u]$ to determine whether $v$ is reachable from $u$. |
| 28 | +- If $v$ is reachable from $u$ in $G^f$, then $uv$ is not a critical edge in $G$. This means the overall flow through flow network $G$ does not need to decrease, and can remain at $C$. We just need to find an alternate route for that unit of flow. We can retrace our steps from $v$ back to $u$ in $G$. For each edge encountered along the way, we increase or decrease the flow along that edge accordingly. If an edge in the uv-path in $G^f$ traveled in the same direction as the corresponding edge in $G$, we add 1 to that edge's flow in $f$. If an edge in the uv-path in $G^f$ traveled in the **opposite** direction as the corresponding edge in $G$, we subtract 1 from that edge's flow in $f$. |
| 29 | +- If $v$ is **not** reachable from $u$ in $G^f$, then $uv$ is a critical edge in $G$. This means the overall flow through flow network $G$ needs to be decreased by 1. Using the same $prev[]$ array, we can trace our steps from $s$ to $u$ in $G$. For each edge encountered along that path, we decrease its corresponding flow in $f$ by 1. We then run a new DFS from $t$ in $G^f$, to produce a path from $v$ to $t$. For each edge encountered along that path, we decrease the flow by 1. |
| 30 | +- We conclude by subtracting 1 from $f_e$ to account for the earlier mistake. |
| 31 | + |
| 32 | +Runtime $O(n+m)$ |
| 33 | + |
| 34 | +## TA Solution |
| 35 | +The TA solution eliminates the conditional check as to whether $uv$ was a critical edge, and cleverly leverages the time complexity of Ford-Fulkerson. |
| 36 | + |
| 37 | +- Create $G^f$ from $f$. |
| 38 | +- Run $BFS(G^f,u)$, and backtrack using $prev[s]$ to find a path that produced at least one unit of flow from $s$ to $u$. We subtract 1 from the flow for each of those edges. |
| 39 | +- Run $BFS(G^f,t)$, and backtrack using $prev[v]$ to find a path that produced at least one unit of flow from $v$ to $t$. We subtract 1 from the flow for each of those edges. |
| 40 | +- Create a new capacity table for all edges in $G$, setting $c_e'=c_e-f_e$. |
| 41 | +- We then run Ford-Fulkerson on $G$ using $c_e'$, producing $f'$. |
| 42 | + - We know that the overall flow through this new flow network ($C'$) is either 0 or 1. |
| 43 | + - If $e$ was a critical edge, the overall flow through $G$ was decreased from $C$ to $C-1$. If this is the case, $C'=0$ |
| 44 | + - If $e$ was not a critical edge, the overall flow through $G$ remains at $C$. If this is the case, $C'=1$ |
| 45 | +- The resulting flow is $f+f'$, with max flow $C-1+C'$ |
| 46 | + |
| 47 | +Runtime: |
| 48 | +- 2 rounds of BFS: $O(n+m)$ |
| 49 | +- Creating the new capacity table: $O(n)$ |
| 50 | +- Ford-Fulkerson: $O(mC):C=1 \therefore O(m)$ |
| 51 | + |
| 52 | +Since we don't know if the flow network is connected: Overall: $O(n+m)$ |
| 53 | + |
0 commit comments