Loading

IOI2025 worldmap的更优做法

题意

给定 \(n\) 个点 \(m\) 条边的无向联通图。你需要构造一个 \(K\times K\) 的网格,并在每个网格点上标上一个点的标号,使得一条边 \((u,v)\) 在图中出现当且仅当网格中存在相邻的两个点,编号分别为 \(u\)\(v\)

数据范围:\(n\le 40\)

要求 \(K\leq \color{red}{1.5n}\)

题解

我们先来看原题的 \(2n\) 做法是怎么做的。

首先,找到图的一颗 DFS 树,并根据颗树的 DFS 序斜着放,像这样:

1232
2324
3242
2421

考虑在这样的图中加入其他非树边。对于每个点的最后一次访问,我们把其拓展为 \(3\) 条斜线,并在中间那条塞入其向祖先连的边,像这样:

  1d1
 1c1
1b1
a1
1

可以发现,这条斜线的位置到斜线序列开头和末尾的长度都至少是其到祖先的深度,因此总是能够在中间夹住所有要连的点。这样需要 \(4n\) 条斜线,完成了 \(K=2n\) 的构造。

然而,这样构建夹层非常浪费,考虑优化。

我们发现我们可以同时处理两个点对应的出边,我们处理了 \(a,b\)\(2\) 的连边、\(c,d\)\(1,2\) 的连边,\(e,f\)\(2\) 的连边:

    1f12
   1e12
  1112
 11d2
12c2
2b2
a2

可以发现,夹层大小大约是 \(1,2\) 两点处理的出边的并集大小。这样平均每个点只在 DFS 序的基础上多用一条斜线。

考虑在树上对相邻的一些点做匹配,然后对这些匹配做上面的连边优化。从根开始从上到下匹配,每次将一个没匹配的非叶子向其最后一个儿子匹配。这样会连成一些匹配,并剩下一些叶子。

由于这些叶子不会相互连边,因此我们只需要将叶子向祖先连出去的那些边放在祖先处处理,我们不对他们建立夹层。

然后,对于每个向儿子匹配的点 \(x\),在其最后一次被访问时(即刚遍历完最后一个儿子时)处理 \(x\) 和其最后一个儿子连出去的需要处理的边。需要处理的点只有 \(x\) 的祖先和 \(x\) 子树内的叶子。我们只需要说明,我们的夹层大小至少能放这么多点,也就是说夹层前面和后面都至少要有这么多点为之。

夹层前面有这么多点是显然的,因为这些点都出现在了夹层的前面;而夹层后面只出现过 \(x\) 的祖先。但是我们发现,我们没有给叶子建立夹层,这为我们在最后省下了叶子个数的空位,因此后面也是能放得下的。

这样我们需要用 \(3n\) 条斜线,完成了 \(K=1.5n\) 的构造。当然,这样的构造也有很多冗余,距离理论最优还有挺大距离。

aclink

posted @ 2025-08-05 12:52  zhoukangyang  阅读(1274)  评论(1)    收藏  举报