diff --git a/om-graphs/graphs.tex b/om-graphs/graphs.tex index 5ccc92e2e9e1f61a56392503cbf655317f9d01b0..15e52bcb3c7fb5d90a6700b157cda3799a681e07 100644 --- a/om-graphs/graphs.tex +++ b/om-graphs/graphs.tex @@ -4,6 +4,8 @@ \fi \def\TODO{{\bf TODO}} +\def\LCA{\op{LCA}} + \chapter[graphs]{Representation of graphs} In this chapter we will peek into the area of data structures for representation of @@ -16,28 +18,30 @@ E)$, where each vertex~$v$ has weight~$w(v)\in\R$.\foot{We could also had weight instead.} We would like to support following operations: \tightlist{o} \:\em{path query} --- find the vertex with minimum weight on a path $u\to -v$;\foot{Generally, we can use any associative operation, instead of minimum.} +v$;\foot{Generally, we can use any associative operation instead of minimum.} \:\em{point update} --- set $w(v) \leftarrow c\in\R$; \:\em{path update} --- increase weight of each vertex on path $u\to v$ by $\delta\in\R$; \:\em{structural update} --- connect/disconnect two trees via edge $(u,v)$. \endlist + \section[path]{Static path} -As a warm-up we build a data structure for $F$ being a path and without structural +As a warm-up we build a data structure for $F$ being a static path, without structural updates. This will also be an important building block for the more general case. Let us denote the vertices $v_1, \dots, v_n$ according to the position on the path and let -us denote $w_i = w(v_i)$. \TODO\foot{maybe change initial notation} We build an interval +us denote $w_i = w(v_i)$. \TODO\foot{maybe change initial notation} We build an range tree~$T$ over the weights $w_1, \dots, w_n$. That is, $T$ is a complete binary tree with $w_1,\dots w_n$ in its leaves (in this order) and inner nodes contain the minimum of their children. Note that each node represents a subpath of~$F$ with leaves being the single vertices. -\TODO picture of path and the interval tree -\figure[]{interval-tree.pdf}{}{\TODO} +\TODO perhaps reference the lecture notes on details about range trees +\TODO picture of path and the range tree +\figure[]{range-tree.pdf}{}{\TODO} % temporary sketch, not in repository -\theorem{Static path representation via interval tree can perform \em{path query}, +\theorem{Static path representation via range tree can perform \em{path query}, \em{point update} and \em{path update} in $\O(\log n)$ time. } @@ -73,4 +77,66 @@ always traverse the tree top-down in order to see correct values in the nodes. % temporary sketch, not in repository \qed + +\section[hld]{Heavy-light decomposition} +Now we are ready build data structure for static trees using \em{heavy-light +decomposition}. We assume our tree $F$ is rooted and we orient all edges +up, towards the root \TODO\foot{maybe unnecessary now}. + +\defn{ +Let~$F$ be a rooted tree. For any vertex~$v$ we define $s(v)$ to be the size of subtree +rooted at~$v$ (including~$v$). Let~$u$ be a child of~$v$, we say the edge~$(v,u)$ is +\em{heavy} iff $s(u) \ge s(v)/2$, otherwise we say $(v,u)$ is \em{light}. Finally, a +\em{heavy path} is simply a path containing only heavy edges. +} + +\obs{ +For any vertex~$v$, there is at most one heavy edge from~$v$ to its children. Therefore, +each vertex~$v$ lies on exactly one heavy path (the path can consist of only~$v$). +} + +\obs{ +Any root-to-leaf path in~$F$ contains at most $\log n$ light edges. +} + +This gives us the decomposition of the tree into heavy paths that connected via light +edges. The decomposition can be easily found using depth-first search in +linear time. + +We represent each heavy path using the range tree structure for static path from the +previous chapter. The root of each range tree will also store the light edge that leads up +from the top of the path and connects it with other heavy path. + +\TODO decomposition example + +The following lemma gives a recipe on how to evaluate path queries and updates: + +\lemma{ +Every path $x\to y$ in~$F$ can be partitioned into $\O(\log n)$ light edges and $\O(\log n)$ +subpaths of heavy paths. +} +\proof +If the path is top-down we have $O(\log n)$ light edges by the previous observation and +these edges split the path into $O(\log n)$ heavy subpaths. Otherwise, path $x\to y$ can +be divided into two top-down paths at the lowest common ancestor of $x$ and $y$. +\qed + +Thus, we just partition the query (update) into $\O(\log n)$ queries on heavy paths plus +light edges. As each subquery can be evaluated in $\O(\log n)$ we get $\O(\log^2 n)$ in +total. + +However, there is a catch. To calculate the partitioning, we need to calculate lowest +common ancestor of~$x$~and~$y$ ($\LCA(x,y)$). + +\TODO + + +\section[linkcut]{Link-cut trees} +\TODO + + +\section{Application: Faster Dinic's algorithm} +\TODO + + \endchapter