Editorial for IOI '05 P6 - Rivers
Submitting an official solution before solving the problem yourself is a bannable offence.
Notation
It is not hard to observe that since for each village there is a unique way down the river from the village to Bytetown, we can treat the rivers and villages as a tree with the root in Bytetown. Nodes of the tree correspond to the villages (for convenience we will refer to Bytetown as a village too), and node is the parent of node when is the first village downriver from .
Let denote the root of the tree, i.e. corresponds to Bytetown. By we will denote the number of edges on a unique path from to . Clearly, the values of can be computed for all villages in linear time. The number of children of node will be denoted by , and the number of trees cut near village will be denoted by .
Dynamic Programming
We can apply dynamic programming to solve the task. Let denote the minimal cost of transportation of the trees cut in the subtree rooted in , assuming that additional sawmills can be built in the subtree, and the trees not processed in can be processed in the village of depth (on the way from to Bytetown). We compute values of for each village , and such numbers , that and . Clearly, when the tree rooted in has at most nodes, then , as we can simply place a sawmill in every village. We can use the following formula:
where is the cost of transportation when there is no sawmill in , and is the cost of transportation when there is one. These costs depend on the distribution of sawmills between subtrees rooted in children of . Let and let be the children of . Then:
Dynamic Programming One More Time
Let us have a closer look at the recurrences (2) and (3). We do not need to consider every partition of into a sum of terms, to compute the values of and . It would be time-consuming in case of trees containing vertices with many children. Once again, we can use dynamic programming. Let denote the cost of transporting the trees cut in subtrees rooted in provided that additional sawmills can be built in these subtrees and the trees not processed in these subtrees are processed in a village of depth . We can make use of the following recurrence:
We define analogously, but this time we assume that the trees not processed in the subtrees are processed in . Then
Obviously, and . In order to compute all values of (respectively ), for some , we compute (respectively ) for each and . It follows that for each pair it takes time to compute values and , giving total time:
since is equal to the number of edges in the tree, i.e. . After computing all values of the program returns as the final answer.
Too Much Dynamic Programming
Using dynamic programming twice would not be required if all the vertices in the tree had a small number of children. Fortunately, we can easily construct a binary tree of villages that has the same minimal cost of transportation as the original one. In order to do this, we connect the first child of each vertex to the parent as its left child, create an additional village and connect it as a right child to the parent. Then we connect the other children of the parent vertex in the original tree one by one, each time connecting a child as a left child of the additional village created during connecting the previous child, creating a new additional village and connecting it as a right child of the previous one. Additional villages produce no wood and rivers connecting them to parents are of length , so they do not affect the total cost of transportation. Building sawmills in additional villages does not lower the minimal cost of transportation, because every sawmill built in an additional village can be moved to the next non-additional village on the way to Bytetown without raising (and even possibly lowering) the total cost.
There are partitions of into a sum of non-negative terms. For each pair we can therefore compute for all in time. There are twice as many vertices in the binary tree as in the original one. The total computation time is:
One River
It is worth noting, that in the special case, where instead of a tree of rivers there is just one river with multiple villages, the problem is significantly simplified and can be solved more efficiently. In such a case we can use simple dynamic programming. Let us number the villages from to upstream. For each village , and for each number of sawmills let us denote by the optimal cost of locating sawmills in the part of the river downstream from . The value of can be computed in time: we check all possibilities of placing the upstream-most sawmill using stored values of . Such an algorithm works in time.
A special case of such a problem — for just two sawmills — appeared at CEOI 2004, but the upper bound on was much bigger: . This required at least an algorithm, which did not use dynamic programming, but was based on the divide and conquer technique instead. There exists also a solution running in linear time, iterating over all possible locations of the uppermost sawmill and finding the optimal location of the other sawmill in amortized constant time.
Comments