Editorial for COCI '13 Contest 5 #6 Ladice
Submitting an official solution before solving the problem yourself is a bannable offence.
The state of drawers and items can be represented by a directed graph where the nodes are drawers and the edges are items. If an item is located in drawer , and its alternative is drawer , the graph contains the edge . Given the fact that each drawer can contain a maximum of one item, the out-degree of all nodes is either or , the path from any drawer is unambiguous and ends in an empty drawer or a cycle of drawers.
If drawer is empty and there if an edge , it is possible to store the item from drawer to drawer , which corresponds to swapping edge with edge . In other words, reversing the associated edge.
If there is a path from a full drawer to an empty drawer , the drawer can be emptied by repeatedly moving items, which corresponds to swapping edges on the path from to .
If a path from a drawer ends in a cycle, that drawer cannot be emptied.
We need a data structure which can tell us whether it is possible to empty a drawer (or if it's empty already) or, in other words, is there a path in the graph to an empty drawer.
Let us mark the empty drawer which is the end of the path from drawer ; additionally, if is empty, then , and if such a path doesn't exist, then (an empty drawer is added as a mark for a cycle).
When adding a new item, the following scenarios are possible:
- If the item is being added in the empty drawer whose alternative is drawer , then for each where , we change into .
- If the drawer needs to be emptied first and then add an item, the same thing happens.
A naive modification of the array final can be too slow for the limitations in this task.
The key thing is to notice how the drawers can be divided into classes considering the final drawer (drawers with equal final drawers are located in the same class), which enables us to implement the relation final efficiently with the union-find structure. A cycle is formed if we add an item whose drawers are both located in the same class.
With the help of the structure, we use a function which corresponds to the aforementioned array and function which performs the substitution described in 1.
When we have defined these functions, the following can be applied:
- For an empty drawer, .
- For a drawer that can be emptied, .
- A cycle is formed when adding items with drawers and if , and if it is added in the structure as .
- Otherwise, a new cycle is not formed and we add the item as (if we are adding the item in the drawer ).
Comments