Editorial for An Animal Contest 7 P5 - Squirrel Scheming
Submitting an official solution before solving the problem yourself is a bannable offence.
Consider the following problem: Given an arbitrarily rooted tree, what is the minimum distance of a path that starts from the root, visits every single node once then returns to the root?
The answer is where is the number of edges in the tree. We traverse each edge once when entering a subtree, and another time when leaving the subtree to return to the root. Overall, we traverse each edge twice so the answer is .
If we don't consider the lexicographic part of the problem, this problem is the exact same as the above except we don't need to return to the root. Think about the maximum distance we can "save" from not returning to the root.
The maximum distance we can "save" is equal to the diameter of the tree. Which means the minimum cost path is equal to where is the number of edges, and is the diameter of the tree.
Find the optimal starting node for a permutation, then build the rest of the permutation.
Let's first find the optimal starting node in the permutation. This node is simply the minimum node that is an endpoint of any diameter in the tree. To find this node, one can simply run a DP on the tree. Let's call this node .
Next, observe that for any diameter , there is a permutation where is the last node and achieves the minimum cost. This is because after we visit we do not need to return to thus saving a cost equal to the length of the diameter of the tree, which is the maximum amount you can save.
This encourages a solution that first fixes the start node and the end node, then constructs the rest of the permutation. As it turns out, knowing the first and last node of the permutation makes the problem a lot simpler.
To get an idea of what the algorithm looks like, consider the following tree:
Clearly, the optimal starting node is and the only diameter we need to consider is . Now, let's recursively build the permutation starting from . For each recursive call to a node , let's sort all of 's children by the minimum value in each child's subtree. After sorting the children, go through the children in increasing order of value. At each child, recursively call the function to the node with the minimum value in that child's subtree. However, we must still consider one final detail: we must end the permutation on the diameter that was fixed. So, when sorting we must also check if any of the subtrees contain the ending node of the permutation. If it exists in a subtree, we must process that subtree last no matter what the minimum value present in the subtree is. After processing all the children, we must return to the original node that the function was called from. For example, in the diagram above, when processing node , we can see that the ordering of the subtrees will be (diameter is present in 's subtree so we automatically process it last). So, we will call the function at node because it is the minimum value in 's subtree. After processing , we must return back to node . However, if we return directly, then we cannot process any other nodes in 's subtree because of the property that every subtree will be entered and exited at most once. Therefore, we must call the function at 's parent. After we call , we can again sort all the nodes in its subtree, ignoring because we already processed , and then recursively call the function on all of the sorted nodes. To keep track of which subtrees to ignore and where to stop calling the function to the parent, pass parameters that keep track of which children have been visited already as well as which node initially called the search into the subtree. Finally, we can run this function for each possible diameter that stems from the optimal starting node and compare their outputs.
Since there are diameters in the worst case, we can no longer afford to run the algorithm directly for each diameter. To optimize, instead of fixing the diameter, we can actually make our sorting slightly more sophisticated to find an optimal diameter. As with the previous algorithm, sort the nodes by the minimum node present in each subtree. However, this time also keep track of which subtrees contain at least one ending of a diameter. Now, instead of fixing the diameter, we can simply process the maximum value subtree that contains at least diameter last.