### Graphs: Dinic

parent e9ac7079
 ... ... @@ -386,5 +386,9 @@ h 160 544 m 75.4718 0 0 -75.4718 200 480 240 544 a L R L R
 ... ... @@ -209,7 +209,7 @@ respective root. It supports following operations: \: Cost queries: \tightlist{-} \:$\opdf{Cost}(v)$; \:$\opdf{PathMin}(v)$ --- return minimum cost on the path $v \to \op{Root}(v)$ \:$\opdf{PathMin}(v)$ --- return minimum cost vertex on the path $v \to \op{Root}(v)$ \endlist \: Cost updates: \tightlist{-} ... ... @@ -450,7 +450,70 @@ so only need to pay $\O(\log n)$ into the potential. \section{Application: Faster Dinic's algorithm} \TODO To show a non-trivial application of link-cut trees we describe how they can be used to make faster Dinic's algorithm. Recall that Dinic's algorithm is an algorithm to find a maximum flow from source vertex~$s$ to a targer vertex~$t$ in network~$G$. We won't describe the algorithm in full detail here and we focus only on the parts important for our application of link-cut trees. The key part of Dinic's algorithm is to find a \em{blocking flow} in the \em{level graph}. A \em{blocking flow} is a flow satisfying the property that every (directed) path from source to target contains a saturated edge, i.e. edge where the flow equals the capacity. The \em{level graph} contains exactly the vertices and edges which lie on some shortest path from~$s$ to~$t$ in the residual network\footnote{Residual network is a network containing the edges with non-zero residual capacity, that is, difference between capacity and a flow. Capacity of each edge in residual network is exactly the residual capacity.}. The important property of level graph is that it is acyclic and it can be decomposed into levels such that there are no edges between vertices in each level, see Figure~\TODO level graph. Dinic's algorithm starts with a zero flow and in each iteration it finds a blocking flow in the level graph and augments the flow with the blocking flow. It can be shown that we need~$n$ iterations to find the maximum flow in~$G$. Traditionally, the search for the blocking flow is done greedily in $\O(nm)$ time, which results in $\O(n^2m)$ complexity of the whole algorithm (construction of the leveled graph etc can be easily done in $\O(m)$ time per iteration). With link-cut tree, however, we can achieve $\O(m\log n)$ time per iteration. We use link-cut trees with weighted edges -- the cost of an edge is its residual capacity. At the beginning of iteration each vertex in the level graph arbitrarily selects a single outgoing edge. These edges form a forest~$F$ oriented towards~$t$ and we build a link-cut tree over~$F$. We also mark the edges of~$F$ as processed. \def\Cost{\op{Cost}} We maintain multiple invariants throughout the algorithm. First, $t$ is always a root of a tree in~$F$ while $s$ is a root if and only if there are no outgoing edges from~$s$ in $F$. Second, each vertex has at most one outgoing edge in~$F$. Finally, $F$ contains only marked edges and if an edge is removed from~$F$, it is never added back to~$F$ again. The search for blocking flow consist of two steps -- \em{augment step} and \em{expand step}. If $\Root(s) = t$ there is a path path from $s$ to $t$ in $F$ and we can perform augment step. We find the minimal edge~$e$ on the path $s \to t$ and perform a path update that decreases costs on $s\to t$ by $\Cost(e)$. This corresponds to increasing the flow on $s\to t$ by $\Cost(e)$. If $\Cost(e) = 0$ we simply cut~$e$ and remove it from $F$. The other step is expand step which is performed when $\Root(s) = r \neq t$. If $r$ has an unmarked outgoing edge~$e$ we simply add~$e$ to~$F$ using $\op{Link}(e)$ and we mark~$e$. However, if there is no such edge, all $s\to t$ paths via~$r$ are already blocked and we may remove~$r$ from~$F$ for good. That is, we remove all edges that lead to~$r$. Marked edges still present in~$F$ are cut and deleted from~$F$, unmarked edges are marked but not added to~$F$. \TODO algorithm pseudocode We repeat these steps until $\Root(s) = s$ and all edges going out from~$s$ are marked. That is, we stop when $s$ would be removed from~$F$ during expand step. Using simple induction, we can easily show that in such case all paths from~$s$ to~$t$ have been blocked and we indeed found a blocking flow. We can see that the number of steps we execute is bounded by the number of edges in the level graph. Augment step either removes an edge from~$F$ or it decrease a cost of an edge to zero so it will be removed in the next step. Expand step either adds an edge to~$F$ or it removes at least one edge. Since we never add an to~$F$ twice we have at most~$\O(m)$ steps. Each step takes amortized~$\O(\log n)$ time which gives $\O(m\log n)$ time per iteration of the algorithm and $\O(nm\log n)$ time to find the desired maximum flow. \endchapter
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!