前言
我们趋行在人生这个亘古的旅途,在坎河中奔跑,在挫折里涅槃,忧愁缠满全身,痛苦飘洒一地。我们累,却无从止歇;我们苦,却无法回避。
今天是连通性的进阶题目,重点是耳分解,双极定向,以及边三连通分量。
因为调题速度过慢,导致被硬控,所以第二天晚上补的差不多了再来写的。
感觉知识点方面也需要写个东西稍微总结一下,看周末有没有时间和心情吧。
A
简单来说,就是选择边权最小的边让原图满足点双连通。
可以发现,这个边权最小的点双连通实际上就是从最开始一个单独的点,一直加相对于当前的点集的开耳,直到整个图上的点都被加进去,然后保证边权和最小。
显然有一个状压 \(\texttt{DP}\),定义 \(dp_S\) 表示当前点集 \(S\),构成一个点双所需要的最小边权。转移的话就是一直向点集 \(S\) 里加相对于它的开耳,直接枚举这个开耳的点集,然后预处理出这个点集形成开耳所需要的最小边权即可,时间复杂度应该是 \(\mathcal{O}(3^n\times \text{polylog}(n))\)。
其实可以考虑稍微优化一下,即不是每次一次性的将整个开耳加进去,而是一个点一个点的加。
即定义 \(dp_{S,i,j}\) 表示上一个加入开耳的点是 \(i\),这个开耳的最后一个点是 \(j\),现在加入开耳的点的集合是 \(S\)。直接枚举 \((i,k)\) 转移,然后当你又一次回到点 \(j\) 的时候,稍微处理一下下一个新开耳的信息就可以了。时间复杂度 \(\mathcal{O}(2^n\times \text{polylog}(n))\)。
需要非常注意重边的情况,比如 \(x\to y\to x\) 这种开耳,你就需要在第二次加入 \(y\to x\) 这条边的时候,边权和计算的应该是 \((x,y)\) 之间所有的重边次小的那一个,因为最小的在 \(x\to y\) 已经被使用了。
我的实现是 \(\mathcal{O}(2^n\times n^3)\) 的。
\(\texttt{Code}\)
B
以前应该做过,但是我再看一遍之后貌似还是不会。
首先,不妨设 \(a\le b\le c\),找一下数量关系,那么显然有:\(c\ge \frac{n}{3},a\le b\le \frac{n}{2}\)。
另外,我们只需要考虑联通的导出子图点集大小分别为 \(a,b\) 的情况,因为如果你凑出了是 \(c\) 的,那么你可以删点得到 \(a/b\)。
观察特殊性质,发现有一档 \(m=n-1\),所以我们先来思考一些树的情况怎么解决。
本质上就是找到一条边 \((x,y)\) 满足 \(x\) 那边的点的个数 \(\ge a\),\(y\) 那边的点的个数 \(\ge b\)。
显然可以通过遍历一次树来判断。
但是其实进一步的,我们可以通过更精确的方式来描述这个合法。
我们其实只需要考虑这个树的重心,如果它能找到一个子树的 \(a\le \text{siz} \le \frac{n}{2}\),那么由于 \(n-\text{siz}\ge \frac{n}{2}\),于是合法。
可以发现只要合法,就必然会存在一个方案跟重心有关,所以我们只需要关注这个重心。
考虑如何扩展到一般图。
显然,为了往树上我们刚刚的方法靠近,我们考虑弄出这个图的搜索树,并求出这个搜索树的重心。
如果这个重心已经可以做到存在一个儿子的大小 \(\ge a\) 了,那么就显然合法,按照刚刚的办法做就可以了。
考虑枚举这个重心的儿子,显然在上面的合法情况排除掉之后,有 \(\text{siz}< a\),看从这个儿子的子树里面,经过非树边能到的其他子树。假设当前儿子是 \(x\),可以到达 \(y_1,...y_m\) 这么多颗其他子树。(我们用重心的儿子来表示这些子树,其实就是这个子树的根)我们一直 \(x+y_1+...+y_{M}\),找到最小的 \(M\) 满足当前的 \(x+y_1+..+y_M\ge a\),就不加了,因为当前的显然已经够满足 \(A\) 了。可以发现,我们最多只会花费 \(2\times a\) 去满足 \(A\),因为 \(a\le x+y_1+..y_M\le 2\times a\) 本质上还是因为 \(x,y_1,...y_M\le a\)。可以发现,\(2\times a+b\le a+b+c=n\),故显然可以在剩下的子树中弄出 \(B\)。于是合法。
当然,如果找不到 \(M\) 能够让所有的子树能到的子树的大小之和都到不了 \(a\) 那么就显然是无解的。
注意一下输出方案的细节。
感觉思路很自然,但是我就是想不到啊啊啊。
\(\texttt{Code}\)