P5659 [CSP-S2019] 树上的数

发布时间 2023-11-01 09:43:08作者: 御坂夏铃

相信大家都看过题,但还请搞清楚是数对应结点编号。这里用 \(a_i\) 表示 \(i\) 号结点对应的数。

对于 \(n\leq 10\) 的数据,全排列出删边的顺序然后模拟,取字典序最小的方案。

对于菊花,仍然考虑删边的顺序,假设删边依次是 \(rt\to v_1,rt\to v_2,\cdots,rt\to v_{n-1}\)

因为每删一条边,对应的叶子就会确定下来,所以最终 \(a_{rt}\to v_1,a_{v_1}\to v_2,a_{v_2}\to v_3,\cdots,a_{v_{n-1}}\to rt\)

构成了一个环,也就是说我们只需要在贪心的时候保证最终能形成一个环。

用并查集维护连通性(其实就是若干条链),再用一个数组记录每个结点是否为链头,每次连边的时候保证不在同一连通块并且保证出点是链头即可。

是否是链尾不用记录,因为我们是从小到大枚举数字的,不会重复访问某个结点。

最后把剩下一条链的头尾相连即可成环。


现在来解决链。

建议先手摸一下搞清楚存在某个数被顺路带到相应点的情况。

同样从每个数的最终归宿入手。假设我们想让 \(a_u\to v\)

显然,\(u\to v\) 路径上的边必须依次删,否则走不通。

其次,\(v\)\(u\) 不在路径上的那两条边要先删。

考虑对于每个点维护一个标记表示该点两侧的两条边的删除顺序:没有限制、先左后右、先右后左。

每次贪心时向左向右找最小结点编号,要满足先前的标记。然后打上新标记。


经过前两档部分分的提示,相信大家已经有那么一点点的感觉了。

同样从小到大枚举每个数再枚举终点。问题就是哪些路径能不破坏先前的决策:

  • 起点出发的那一条边必须是起点的最先删边。
  • 抵达终点的那一条边必须是终点的最后删边。
  • 路径上相邻的边在它们共有的点那里必须是连续删除的。

考虑把每个点的边单独拉出来仿照菊花的做法建立一张图,这样就可以通过连边形成决策链(前一条删的边向后一条删的边连边)的方式钦定删边顺序。

成为最后删边的条件:

  • 出点尚未成为过终点。
  • 该边不存在作为连续删的前一条边的约束。
  • 除了该边外出点的决策已经全部完成;或者最先删边(暂时不存在也可以)和该边不位于同一条决策链。

成为最先删边的条件:

  • 入点尚未成为过起点(同样不用判)。
  • 该边不存在作为连续删的后一条边的约束。
  • 除了该边外入点的决策已经全部完成;或者最后删边(暂时不存在也可以)和该边不位于同一条决策链。

成为中间连续两条边的条件:

  • 入边不是该点最后删边或者该点只存在一条边。
  • 出边不是该点最先删边或者该点只存在一条边。
  • 两边不在同一条决策链中。
  • 入边不存在作为连续删的前一条边的约束。
  • 出边不存在作为连续删的后一条边的约束。
  • 连接两条决策链后中间点的决策已经全部完成;或者最先删边和最后删边仍然不位于同一条决策链。