[NEERC2016]Cactus Construction
tag:构造
一道很有意思的构造题
首先考虑树怎么做:
- 叶子节点把颜色改为 \(2\)。
- 非叶子节点把颜色改为 \(3\)。然后先处理完所有儿子,再将所有儿子集合与当前点合起来。然后连 \(2,3\),即把所有儿子和当前点连起来。再改 \(2\) 为 \(1\),改 \(3\) 为 \(2\)。
可以发现每个节点处理完后,都满足:
- 当前点颜色为 \(2\)
- 子树内所有其他点颜色为 \(1\)
- 子树内所有边都已经连好了
所以如果是树的话,只需要 \(3\) 种颜色就够了
推广到仙人掌上,建出圆方树,对于圆点的操作和树一样,考虑方点(环)怎么处理。
设当前方点 \(x\),父亲为 \(y\)。那么找到 \(x\) 对应的环,顺次处理这个环。沿用之前的思路,我们保证每一个点处理完后颜色都为 \(2\),且集合内其他点颜色都为 \(1\)。于是我们依次合并两个相邻的儿子,设为 \(a,b\)。
- \(r\ a\ 2\ 3\)
- \(j\ a\ b\)
- \(c\ a\ 2\ 3\)
- \(r\ a\ 3\ 1\)
这样操作后,就连了一条 \((a,b)\) 的边,而且让 \(a\) 的颜色改为了 \(1\)。
但是问题来了,到了最后一步我们需要把这条链的头尾连起来,怎么办呢?
这个时候就用上第 \(4\) 种颜色了,对于第一个处理的节点,合并后我们不把它的颜色改为 \(1\),而是改为 \(4\)。这样的话是不会影响连这条链的过程的,而且最后做一次连 \(2,4\) 操作就可以把头尾连起来,然后再做一次改 \(4\) 为 \(1\) 保证性质。
关于操作次数,此题 \(10^6=20n\),也就是说一个点能够进行 \(20\) 次操作,显然我们的操作数远达不到这个上限。
上述就是大体思路,不过这题细节十分多。
细节1
在连链的时候,要分三类:
- 第一个点
- \(r\ x\ 2\ 4\)
- 第二个点
- \(j\ x\ prv\)
- \(c\ x\ 2\ 4\)
- 其他点
- \(r\ prv\ 2\ 3\)
- \(j\ x\ prv\)
- \(c\ x\ 2\ 3\)
- \(r\ x\ 3\ 1\)
细节2
在具体实现方点的时候,假设方点 \(x\),父亲 \(y\)。那么可以把这个环除了 \(y\) 之外的点先连成一条链。根据构建过程,这根链满足头为 \(4\),尾为 \(2\),其余点为 \(1\)。所以可以做:
- \(r\ \text{链}\ 2\ 4\)
- \(j\ \text{链}\ y\)
- \(c\ y\ 2\ 4\)
- \(r\ y\ 4\ 1\)
这样就一下连了两条边。(如果当前 \(y\) 的颜色为 \(1\),则还需要一次操作把 \(y\) 的颜色改为 \(2\))
细节3
由于在实现方点的时候,我们会修改 \(y\) 的颜色。所以在处理圆点 \(x\) 的时候,如果有至少一个儿子是方点,就不执行改颜色的操作! 因为这样会把 \(y\) 集合中其他 \(1\) 改为 \(2\)(WA on 34
)。当然也要特判没有方儿子的时候,做一次改颜色 \(1\) 为 \(2\) 的操作。