【Topcoder 10384】KingdomMap

Topcoder 10384

题意:给你一个森林,求是否能将这个森林的点集分成两部分,每部分放在一列中,要求边是直的并且不能交叉,问最少删哪几条边。

思路:我们考虑森林中的一棵树,以\(u\)为根,将\(u\)放在第一列。然后发现\(u\)的儿子们都应该放在第二列,并且如果我们不删掉\(u\)的这个儿子被放在了中间(即非最上和最下),它只有一种选择:将其所有的儿子到它的边删掉,将它们挪到其它地方。如果这个儿子在最上或最下,那么这个儿子可以取另一个可以有儿子的儿子,剩余的也必须没有儿子。

那么我们就有一个想法了。考虑\(dp(u,i)\)表示对于\(u\)这个节点,它可以取\(i\)个能取儿子的儿子,最少删边数。

我们考虑转移。对于\(dp(u,0)\),我们不能有能够取儿子的儿子,那么对于每一个儿子,我们的做法是这样的:要么我们将\(u\)到这个儿子的边断掉,将这个儿子挪到别处;要么我们留下这条边,但是我们必须将这个儿子到它所有儿子的边删掉。

然后就会发现我们需要考虑对于一个节点\(u\)我们断掉它到它所有儿子的边的代价。对于第\(i\)个儿子就是\(1+dp(son_i,2)\)。我们记这个值为\(val_i\)。

然后考虑\(dp(u,1)\)。我们可以取\(1\)个能延伸其它儿子的儿子。枚举那个儿子\(i\),那么\(dp(u,1)\)就是

\(dp(u,0)-val_i+dp(son_i,1)\)。

再考虑\(dp(u,2)\),也是一样枚举那两个可以延伸儿子的儿子,\(dp(u,2)\)取

\(dp(u,0)-val_i-val_j+dp(son_i,1)+dp(son_j,1)\)。

其实这样少考虑了一种情况(就像我原先一样。

如果当前节点\(u\)取了\(1\)个儿子\(i\),并且这个节点所挂子树是被孤立出去的,也就是说这个\(i\)是可以取两个延伸出去的儿子的,这可以让一些答案变少,比如我们断掉一个节点到它所有儿子的代价就会相应地变少。

那我们再来求这个取一个儿子的代价是什么。

首先肯定要将其它的儿子都断掉向它们的边,然后再取\(dp(son_i,2)\)就行了。

那么最后就是考虑怎么求方案了。

这个过程非常血腥暴力,是这样的:我们从头开始枚举每一条边,如果我们将这条边断掉之后再求一遍的答案也相应地减了\(1\),就说明我们可以将这条边给断掉,由于要求字典序最小就将它加到答案中。

需要注意如果这条边可以被断掉那就真正断掉它。

上一篇:Easing圆环动画


下一篇:ArcGIS Server开发教程系列(2)配置ARCMAP和ARCCatalog发布服务