makrav's blog

By makrav, history, 3 months ago, In English

Hello Codeforces!

I was solving this problem, and the model approach involves HLD solution, however I came up with some interesting approach with centroids. In short, I wrote $$$dp_{v, cnt, mask}$$$ where $$$v$$$ is vertex in tree in which centroid subtree I am choosing edges, $$$cnt$$$ is number of edges that was taken to the matching and $$$mask$$$ is mask of vertices which were already taken to some of matching edges, but we only consider those vertexes which have edges to vertices outside of $$$v$$$'s centroid subtree.

So this solution works in $$$O(C \log n)$$$ where $$$C$$$ is number of different $$$dp$$$ states, which is equal to $$$\displaystyle\sum_{v=1}^{n} siz_v \cdot 2^{edges}$$$ where $$$siz_v$$$ is size of $$$v$$$'s centroid subtree, and $$$edges$$$ is number of different edges from tree going outside from $$$v$$$'s centroid subtree.

Here is the proof that number of different states is $$$O(n \log^2 n)$$$. Let me know if you notice any mistakes. Thanks to zwezdinv for helping me with proving this.

Let's consider centroid tree which is built recursively like this: we delete the centroid from the tree, build centroid tree for all remaining components and connect roots of these centroid trees to current centroid. For each vertex $$$v$$$ let's consider value $$$c_v$$$ which equals to number of edges going outside the centroid subtree $$$v$$$ to other vertices. Obviously each edge from original tree is vertical path in centroid tree (because one of edge's endpoints is parent of other one in centroid tree). So each edge $$$(u, v)$$$ from original tree where $$$u$$$ is parent of $$$v$$$ in centroid tree adds $$$1$$$ to values $$$c_w$$$ for all $$$w$$$ on path from $$$u$$$ to $$$v$$$ in centroid tree except of $$$u$$$. For simplicity, let's extend each edge from original tree to any leaf in centroid tree. This will only increase $$$c_w$$$ values for some $$$w$$$, so the bound will still be proven.

Let's calculate $$$T(n, s)$$$ which corresponds to bound of $$$C$$$ value for any centroid subtree with exactly $$$n$$$ vertices if $$$c_{root} = s$$$ where $$$root$$$ is the root of this centroid subtree (e.g. $$$s$$$ is number of edges that are going from parents of $$$root$$$ in centroid tree). Want to prove, that $$$T(n, s) \leq n \cdot log_2(n) \cdot 2^s + n \cdot log_2(n)^2$$$.

Suppose $$$n_1, n_2, n_3, \dots n_k$$$ are sizes of children subtrees and $$$s_1, s_2, s_3, \dots s_k$$$ are $$$c_w$$$ for these subtrees roots. We know that $$$\displaystyle\sum_{i=1}^k n_i = n - 1$$$, $$$n_i \leq \frac{n}{2}$$$ and $$$\displaystyle\sum_{i=1}^k (s_i - 1) = s$$$ (because each edge from $$$s$$$ upper edges is going exactly to one of subtrees and one edge from $$$root$$$ appears). Prove by induction, then $$$T(n, s) = n \cdot 2^s + \displaystyle\sum_{i=1}^k T(n_i, s_i) \leq n \cdot 2^s + \displaystyle\sum_{i=1}^k (n_i \cdot log_2(n_i) \cdot 2^{s_i} + n_i \cdot log_2(n_i)^2) \leq$$$

$$$\leq n \cdot 2^s + 2 \cdot (log_2(n) - 1) \displaystyle\sum_{i=1}^k n_i \cdot 2^{s_i - 1} + (log_2(n) - 1)^2 \cdot \displaystyle\sum_{i=1}^k n_i$$$

We know that $$$\displaystyle\sum_{i=1}^k n_i \cdot 2^{s_i - 1}$$$ with $$$\displaystyle\sum_{i=1}^k (s_i - 1) = s$$$ is maximal when one $$$s_i - 1 = s$$$, where $$$n_i$$$ is maximal and other $$$s_i - 1 = 0$$$, so above sum is not greater than

$$$n \cdot 2^s + 2 \cdot (log_2(n) - 1) \cdot (n + \frac{n}{2} \cdot (2^s - 1)) + (log_2(n) - 1)^2 \cdot n \leq$$$

$$$\leq n \cdot 2^s \cdot log_2(n) + n \cdot log_2(n)^2 - n \cdot log_2(n) \leq$$$

$$$\leq n \cdot 2^s \cdot log_2(n) + n \cdot log_2(n)^2$$$

So the bound is proven.

$$$C$$$ equals to $$$T(n, 0) \leq n \cdot log_2(n)^2 + n \cdot log_2(n) = O(n \cdot log_2(n)^2)$$$.

Also there is a lower bound of $$$\Omega(n \cdot \log_2(n)^2)$$$.

Let's build centroid tree that is full binary tree. Divide this tree into paths to leaf and add to the actual tree the direct edge from every vertex in path to end of this path. Also we direct one more edge from every vertex to subtree that is not on path that this vertex lies in. We can see this is valid centroid tree by proving it inductively. If both subtrees of root are valid centroid trees and root is connected to both of them and divides them into components of size less than half of size of all tree, so root is centroid and transition is proved.

$$$S(k)$$$ denotes $$$C$$$ for such full binary tree of depth $$$k$$$. Consider path that is going from root. This path impacts to $$$C$$$ not less than $$$\displaystyle\sum_{i=0}^k 2^i \cdot 2^{k - i} = 2^k \cdot (k + 1)$$$. If we delete these path, there will be components of depth $$$0, 1, \dots k-1$$$, so $$$S(k) \geq 2^k \cdot (k + 1) + \displaystyle\sum_{i=0}^{k-1} S(i) = \displaystyle\sum_{i=0}^k 2^i \cdot (i + 1) \cdot 2^{k - i} = \frac{2^k \cdot (k + 1) \cdot (k + 2)}{2} = \Omega(n \cdot log_2(n)^2)$$$, so bound is proven and $$$C$$$ is $$$\Theta(n \cdot log_2(n)^2)$$$.

Here is my code for the problem above from 300iq contest.

Also this technique can be used to solve this problem from APIO.

UPD: There is a way to reduce the runtime to $$$O(n \cdot log_2(n))$$$. Thanks to dooglius for providing this beautiful solution! Here is how it works:

Let's build our "pseudo-centroid" tree recursively. On each iteration we have some set of vertices which will correspond to some centroid subtree in our final construction. Also, some of these vertexes from the set already have edges from original tree going outside of this set. We want to keep number of such vertex $$$\leq 2$$$ at every moment. Obviously, at each stage we want for these vertexes to form a connected subgraph of the initial tree.

If there are $$$\leq 1$$$ vertexes with edges going outside of current set, let's pick the centroid of our set in the initial tree and run recursively from each of its subtrees from the set. After this operation, each of centroid's subtrees would have $$$\leq 2$$$ edges going outside of the subtree (one edge is added from the centroid), so our condition is still kept.

The tricky case is when we have exactly $$$2$$$ vertexes with outside edges. In this case, let's root our current tree (we build a tree using only vertexes from the set and edges from the original tree) and root this tree by its centroid. Then suppose two vertexes with outside edges are $$$u, v$$$. Let's take $$$LCA(u, v)$$$ as our new splitting vertex and run the recursive process for each of its subtrees.

Now let's talk about the complexity. In the first case when we have $$$\leq 1$$$ vertexes with outside edges, each size of subtree is $$$\leq \frac{s}{2}$$$ where $$$s$$$ is original size of the tree. In the second case, every subtree of $$$LCA(u, v)$$$ has size $$$\leq \frac{s}{2}$$$ because the tree was rooted by its centroid, and each one of those subtrees has obviously $$$\leq 2$$$ vertexes. However, the upper subtree of $$$LCA(u, v)$$$'s size might be $$$\geq \frac{s}{2}$$$, however, this upper tree would have only one vertex with edge going outside (which is connected to $$$LCA(u, v)$$$), so after another iteration its size will decrease by factor of two because it's the first case. So the size of the tree decreases by factor of two in every two operations, therefore the tree's height is $$$\leq 2 \cdot log_2(n)$$$, and the final complexity is $$$O(n \cdot log_2(n))$$$.

Furthermore, the obtained decomposition still has all the properties of usual centroid decomposition.

I think this technique can be called "centroid pro max". Suggest other names if you have ideas!

  • Vote: I like it
  • +327
  • Vote: I do not like it

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by makrav (previous revision, new revision, compare).

»
3 months ago, hide # |
 
Vote: I like it -86 Vote: I do not like it

damn bro , I didn't understand anything but would give my upvote as u are a lgm .. Maybe oneday i would be able to understand these things

»
3 months ago, hide # |
Rev. 2  
Vote: I like it +37 Vote: I do not like it

I think a factor of $$$\log (n)$$$ can be taken out by adding extra nodes to make a "quasicentroid" tree. Whenever we have a tree of size $$$s$$$ with $$$ \lt 2$$$ edge vertices, take the centroid normally as our quasicentroid. But when there are $$$2$$$ edge vertices $$$u,v$$$, instead of the centroid, pick $$$\text{LCA}(u,v)$$$ in the centroid-rooted tree as our quasicentroid. Then one child tree has one edge vertex and size up to $$$s-2$$$ (so it will pick the centroid and halve the size on the next step) and the other children have size at most $$$s/2$$$ and $$$ \lt =2$$$ edge vertices. This quasicentroid tree then has max depth $$$O(\log (n))$$$ and no more than two edge vertices, so the resulting $$$C$$$ is straightforwardly $$$O(n\log (n))$$$

  • »
    »
    2 months ago, hide # ^ |
     
    Vote: I like it +25 Vote: I do not like it

    I don't really understand your approach.

    1) Do you initially add additional vertex for each edge in original tree and this new vertex is connected to both edge ends?

    2) Why after picking $$$LCA(u, v)$$$ some of its subtrees would have only one edge vertex? Can't there be many subtrees of one single centroid, each one of which has many edge vertices in it? What is even $$$LCA(u, v)$$$? You build centroid decomposition on new tree with additional vertices for edges?

    • »
      »
      »
      2 months ago, hide # ^ |
       
      Vote: I like it +33 Vote: I do not like it

      Let me try and explain my thinking better. We can generalize the notion of a centroid tree to work on an arbitrary vertex-picking function $$$f$$$ mapping a tree $$$T$$$ to some $$$v\in T$$$. We create our $$$f$$$-decomposition recursively:

      function decompose(f,T):
        let v=f(T)
        remove v from T, letting S_1,...,S_k be the resulting forest
        foreach i in [1,k]:
          let D_i = decompose(f,S_i)
          connect v to the head of D_i
        return the resulting decomposition tree rooted at v
      

      This is precisely the centroid decomposition tree when $$$f$$$ is a centroid-picking function. However, the things we care about from a centroid tree don't actually require $$$f$$$ to pick a centroid, all we need is that the decomposition tree has height $$$O(\log(n))$$$; we can use any other $$$f$$$ that results in an $$$f$$$-decomposition tree of height $$$O(\log(n))$$$ and it works just as well. This means we have some freedom to make $$$f$$$ pick more convenient vertices. I am proposing a modified choice of $$$f$$$ for this scenario, which bounds the number of boundary vertices (of any subtree in the decomposition tree, with respect to connectivity in the original tree) to be <=2:

      function f(T):
        let c = centroid(T)
        if T has <2 boundary vertices: return c
        else:
          let u,v be boundary vertices 
          let T_2 be T rooted at c
          return LCA(u,v) in T_2
      
      • »
        »
        »
        »
        2 months ago, hide # ^ |
         
        Vote: I like it +18 Vote: I do not like it

        I get it now, thanks. It's fascinating how adding 2^something factor doesn't change runtime at all. How did you come up with this? Is it well known or something? I haven't seen this idea before...

        • »
          »
          »
          »
          »
          2 months ago, hide # ^ |
           
          Vote: I like it +18 Vote: I do not like it

          I think I have seen the trick of divide and conquer while maintaining some bound by alternately choosing between steps dividing and steps lowering the bound, though not on trees and I don't recall the specifics.

        • »
          »
          »
          »
          »
          2 months ago, hide # ^ |
           
          Vote: I like it 0 Vote: I do not like it

          I think this is very similar to the main principle behind top trees

      • »
        »
        »
        »
        2 months ago, hide # ^ |
         
        Vote: I like it +28 Vote: I do not like it

        Added your approach to the blog. Thanks again for leaving the comment and improving our result! Your idea is truly ingenious.

»
2 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by makrav (previous revision, new revision, compare).

»
2 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by makrav (previous revision, new revision, compare).

»
2 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by makrav (previous revision, new revision, compare).

»
2 months ago, hide # |
 
Vote: I like it +18 Vote: I do not like it

300iq centroid decomposition

»
2 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

"Logarithmic depth tree decomposition of tree with bounded width"

https://en.wikipedia.org/wiki/Treewidth

In essence, the construction you came up with can be generalized to the case of arbitrary graphs with limited treewidth. For example, for cacti, for grid graphs with limited height and similar structures, there is a similar approach.

In some ways, this approach is even easier to understand. In a matching problem of a given size, you're essentially only interested in a certain set of vertices that could potentially later be included in the matching. You also want each edge to have a point in time when information about both its endpoints is available.