Commit 56200b30 authored by Ondřej Mička's avatar Ondřej Mička
Browse files

Graphs: Dinic

parent e9ac7079
<?xml version="1.0"?>
<!DOCTYPE ipe SYSTEM "ipe.dtd">
<ipe version="70212" creator="Ipe 7.2.13">
<info created="D:20210602142000" modified="D:20210819155938"/>
<info created="D:20210602142000" modified="D:20210825104345"/>
<ipestyle name="basic">
<symbol name="arrow/arc(spx)">
<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
......@@ -386,5 +386,9 @@ h
160 544 m
75.4718 0 0 -75.4718 200 480 240 544 a
<text matrix="0.605699 0 0 0.605699 117.14 254.272" transformations="translations" pos="88 440" stroke="black" type="label" width="6.78" height="6.808" depth="0" valign="baseline" style="math">L</text>
<text matrix="0.605699 0 0 0.605699 189.14 254.272" transformations="translations" pos="88 440" stroke="black" type="label" width="7.641" height="6.808" depth="0" halign="right" valign="baseline" style="math">R</text>
<text matrix="0.605699 0 0 0.605699 305.14 238.272" transformations="translations" pos="88 440" stroke="black" type="label" halign="right" valign="baseline" style="math">L</text>
<text matrix="0.605699 0 0 0.605699 333.14 258.272" transformations="translations" pos="88 440" stroke="black" type="label" valign="baseline" style="math">R</text>
......@@ -209,7 +209,7 @@ respective root. It supports following operations:
\: Cost queries:
\:$\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)$
\: Cost updates:
......@@ -450,7 +450,70 @@ so only need to pay $\O(\log n)$ into the potential.
\section{Application: Faster Dinic's algorithm}
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
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.
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.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment