Codeforces 1868D. Flower-like Pseudotree

发布时间 2023-09-23 19:57:17作者: DeaphetS

题目链接:D - Flower-like Pseudotree

题目大意:给定度数数组 \({d_n}\),要求构造一个 \(n\) 个点 \(n\) 条边的连通图(也就是基环树),允许有重边,但不能有自环。需要满足第 \(i\) 个点的度数恰好为 \(d_i\),并且将环上的边全部删去后,剩下的每棵树的高度(以原先在环上的点为根)相同。

首先考虑几个特殊情况:

  • \(\sum d_i\neq 2n\) 时,无解
  • \(\forall i,d_i=2\),则直接输出一个大小为 \(n\) 的环

将构造分两步完成,先将非叶子结点全部安排好以完成深度限制,然后再把所有叶子结点连到这些点上以符合度数限制,其中后者做法平凡。基于这一点考虑,如果不存在度数为 \(2\) 的点,那么直接把所有非叶子结点连成一个环就能完成第一步构造。剩下的情况都是必然存在一个度数为 \(2\) 的点的。

接下来,考虑在环上延伸出点以完成构造。这时发现由于在环上的点度数必须 \(\gt 2\),而环的大小至少为 \(2\)。所以若度数 \(>2\) 的点数为 \(1\) 则无解。显然,若不在环上的非叶子结点个数是环大小的倍数,那么直接在环上挂几条长度相等的链即可。于是对环长为 \(2\) 的情况进行讨论。

若钦定了环长为 \(2\),那么只需要判断剩余的非叶子结点个数是否为偶数,若是则直接可以完成构造。若不是,那我们先尽量让两边的链长平均,这样有一边会多出来一个点 \(x\) ,考虑将这个多出来的点移到某个深度比 \(x\) 小的点 \(y\) 后面,让他作为 \(y\) 的儿子。

此时,\(dep(x)=dep(y)+1\),于是只需保证在删去\(x\) 后,\(y\) 不是当前基环树上的叶子结点即可。那么可以在一开始放链的时候,优先让 \(d_i\) 大的点先连(深度更小),这样 \(x\) 在找爹的时候,直接找深度最浅的有空位的父亲即可,这样做一定是较优的。

接下来说明用上述方法无法完成构造时,一定无解,不感兴趣可跳过。

先考虑无法构造时,是什么样的一种情况。

此时一定是 \(x\) 在找爹时,找不到一个比当前爹深度更浅的,且有空位的新爹了。

由于我们是优先连 \(d_i\) 更大的点,所以此时所有的点一定都没有空位,那么显然除了和当前 \(x\) 的父亲深度一样的两个点,其它点的 \(d_i\) 一定为 \(2\),而环上的两个点 \(d_i=3\)

\(x\) 的父亲深度 \(\gt 1\)(环上的点深度看做 \(0\))时,深度为 \(1\) 的点没有空位,那么其 \(d_i\) 一定为 \(2\)。对应非叶子结点的 \(d_i\) 可重集的情况就是 \(\{3,3,2,2,2,\dots\}\),其中 \(2\) 的个数为奇数。那么显然此时只能有两个点在环上,因为有叶子时度数为 \(2\) 的点不能在环上。于是无法通过调整环长来求解,对应情况无解。

\(x\) 的父亲深度为 \(1\) 时,此时是深度为 \(0\) 的点没有空位,对应情况则为 \(\{3,3,3,2,2\}\)\(\{3,3,3,3,2\}\)。此时虽然可以调整环长,但是调整环长后剩下的非叶子结点不足以连出一条长度为 \(1\) 的链,所以也无解。

\(x\) 的父亲深度为 \(0\) 时,那么此时情况为 \(\{3,3,2\}\),与 \(x\) 的父亲深度 \(\gt 1\) 的情况一样,也是无解的。

那么完成几个特殊情况的判断后,贪心连链即可。由于需要找新爹的点最多只会有一个,所以直接特殊钦定一个点用于接收可能出现的这个孤儿就好。

以上内容均为口胡,代码我还没写,但感觉很对。先打 ABC 去了(