图论做题记录-2
ARC161E. Not Dyed by Majority (Cubic Graph)
通过较为精湛的打表和猜测分析,我们惊讶地发现,对于任意一组解,能找到与之对应的初始状态的概率并不高,这启发我们随机给出一组解,然后判断其是否可行。那么如何判断一个解是否可行呢?我们考虑一个点要么为 B,要么为 W,这是典型的 2-sat,于是我们考虑用 2-sat 限制这个内容,于是问题在 \(O(n)\) 的复杂度内得解。
AGC056C. 01 Balanced
不难想到将 \(0\) 看作 \(1\),将 \(1\) 看作 \(-1\) 对原序列求前缀和 \(s\),那么我们有 \(|s_i-s_{i-1}|=1\)。考虑对于给出的限制,相当于指出 \(s_{l-1}=s_r\)。我们看出可以利用差分约束限制,即我们将上述式子看作:
因为要求字典序最小,所以每一个位置的 \(s\) 要尽可能大,因此可以跑一遍最短路,上界就是答案对应的 \(s\),然后做一遍差分即可。最短路可以用 01bfs 解决,复杂度是 \(O(n+m)\) 的。
CF1163F. Indecisive Taxi Fee
观察不同的边对答案不同的贡献,我们发现:不在最短路上的边改动后,答案为原最短路和包含这条边的最短路替换边权取最小值;在最短路上的边改动后,答案为原最短路替换边权和不包含这条边的原最短路。注意到原最短路、原最短路替换边权是容易的,接下来考虑如何求解其他的内容。
对于包含某条边的最短路,对于边 \((u,v)\) 容易想到其路径应当为 \(s\to u\to v\to t\) 或 \(s\to v\to u\to t\),不难看出我们只关心 \(s\to u+v\to t\) 和 \(s\to v+u\to t\) 的值,因此可以分别从 \(s,t\) 开始跑一遍最短路,这样可以 \(O(1)\) 求出经过边 \((u,v)\) 的最短路,替换边权是容易的。
对于最短路上不包含某条边的最短路,可以考虑到其他每一条边地最短路总是通过一段最短路上的前缀 + 一段非最短路 + 一段最短路上的后缀得到,那么看出来这条路径不包括最短路上的某些边,可以借由这一点进行操作。更具体的,对于非最短路的一条边,我们求出经过其的最短路上前缀和后缀的信息,即在哪个位置路径开始分离,记为 \(L,R\),那么这两点之间的所有边都有这条路径的贡献,区间取 \(\min\) 即可。这个可以用线段树实现,复杂度是 \(O(\log n)\) 的。
综上,我们可以在 \(O((n+m+q)\log n)\) 的复杂度内解决这道题。
LG3511. [POI 2010] MOS-Bridge
看到最大边权最小,我们想到二分。对于二分出的 \(x\),显然只能选择边权 \(\le x\) 的方向边去走,我们考虑怎样验证新图中是否包含一个欧拉回路。考虑有向图为欧拉图的充要条件:每一个点的出度入度各占其度数的一半,相当于我们需要判断是否存在一种定向方式,使得每一个点的入度恰为 \(\frac{\text{deg}}{2}\)。考虑使用网络流,对每一个边连向其可行定向对应的起点,那么每一个点的度数上界为 \(\frac{\text{deg}}{2}\),存在一种合法方式当且仅当所有边均跑满,也就是最大流。注意对于原图存在欧拉回路而言,还要求每一条边必须至少存在一个可行的方向,这个可以通过控制二分的下界解决。
跑出最优解后,可以根据残量网络进行边的定向,最后跑出一个欧拉回路后输出即可,复杂度是 \(O(\text{AC})\)。
CF1458D. Flip and Reverse
我们考虑在数轴上对应一个字符串:将 \(0\) 看作 \(-1\),相应的 \(1\) 看作 \(1\),从 \(0\) 开始,遇到 \(0\) 向反方向走一个单位长度,遇到 \(1\) 向正方向走一个单位长度,于是我们将每一个字符串在数轴上对应了一条路径。现在考虑操作的影响,通过观察我们发现一次操作相当于选择一个环,将你走这个环的顺序颠倒。也就是说对于原字符串建出的图来说,走边的顺序是不重要的,因为我们可以颠倒走边的顺序,因此我们对于原图的边重新定一个顺序从而找到一个对应字符串字典序尽可能小的方案。
考虑到一个字符串对应的图一定满足其是一个从 \(0\) 出发的欧拉路径,那么我们可以贪心的每一次尝试走 \(0\),如果走 \(0\) 后一定不合法那么只能走 \(1\),否则总有方案使得当前字符串合法。考虑不合法的情况,可以分为以下几种:
- 前驱的度数为 \(0\)。
- 前驱的度数为 \(1\),自己的度数不为 \(1\)。
否则定然存在合法解,于是问题解决,复杂度是 \(O(n)\) 的。
LOJ6271.「长乐集训 2017 Day10」生成树求和 加强版
看到所有生成树的权值和,我们已经迫不及待想要使用矩阵树定理解决这个问题了,然而每一个生成树的权值的定义让我们难以处理。考虑到对于一个树而言,其最终权值的三进制位之间互不干扰,于是我们可以考虑拆位,即考虑第 \(i\) 位为 \(0,1,2\) 的生成树分别有多少个。
对于每一位,我们可以先求出每一条边的权值,进而去求解生成树的权值,然而不进位加法我们处理起来较为困难,如果想要利用矩阵树定理,那么我们需要将其转化成乘法。考虑一个在乘法中具有循环特性的内容:单位根,我们有 \(\omega_{K}^{i}\omega_{K}^j=\omega_{K}^{(i+j)\bmod K}\),这完美符合我们的要求。于是我们可以将权值 \(0,1,2\),分别替换为 \(1,\omega_{3}^i,\omega_{3}^{2i}\)(以下将 \(\omega_{3}\) 简称为 \(\omega\) ),如果边权为 \(0,1,2\) 的生成树分别有 \(A,B,C\) 个,这样可以求出 \(\omega^{0}A+\omega^{i}B+\omega^{2i}C\) 的值,于是代入 \(i=0,1,2\) 即可详细解出 \(A,B,C\) 的值。
考虑在这个过程中,我们较难维护答案的值:我们容易求得 \(w=a+bi\) 的形式,然而关注到 \(\omega^{2}=-\omega-1\),于是所有数字都可以表示成 \(a+b\omega\) 的形式,那么我们可以维护这样一个结构体。对于这样的数,加减操作不必多说,考虑乘法和逆元的影响:
利用高斯消元快速求解这个内容,复杂度是 \(O(n^3\log_3V)\) 的。
LG5470. [NOI2019] 序列
首先问题可以简单用网络流建模:首先建立一个假源点,用于限制恰好选 \(K\) 个位置,也就是源点向假源点连接一条流量为 \(K\),费用为 \(0\) 的边。接着对于每一个位置,认为选择当且仅当其和源点或汇点的连边有流量,即连接源点和 \(A\) 对应的所有位置,汇点和 \(B\) 对应的所有位置,流量为 \(1\),费用为对应的值。然后每一个位置可以两者都选,也就是对应的 \(A,B\) 直接连边,流量为 \(1\),费用为 \(0\)。同时还可以不对应,我们可以新建立两个点 \(p,p'\),用 \(u\to p\to p'\to v\) 表示选择了两个不对应的位置,显然所有边的费用为 \(0\),\(u\to p,p'\to v\) 的流量为 \(1\),因为至少需要有 \(L\) 个位置都选,那么 \(p\to p'\) 的流量最多只能有 \(K-L\)。对这个图跑一遍最大费用最大流即可。
然而考虑到费用流的复杂度较高,难以接受,我们考虑手动模拟费用流的增广过程。可以分为以下几种情况:
- 选择了之前没有选过的 \(a_x,b_x\)。可以直接连接。
- 选择了之前没有选过的 \(a_x,b_y\)。可以直接连接,但是这样会占用一个特殊流量,所以只有在有特殊流量的时候才能连接。
- 选择了之前没有选过的 \(a_x,b_y\),但是 \(b_x,a_y\) 是选过的。可以考虑将连接 \(b_x,a_y\) 的两个点连到一起,这样我们就可以连接 \(a_x\to b_x,a_y\to b_y\),这样可以省掉一个特殊流量。
- 选择了之前没有选过的 \(a_x,b_y\),但是 \(b_x\) 是选过的。可以考虑将连接 \(b_x\) 的点和 \(b_y\) 连到一起,这样我们就可以连接 \(a_x\to b_x\)。
- 选择了之前没有选过的 \(a_x,b_y\),但是 \(a_y\) 是选过的。可以考虑将连接 \(a_y\) 的点和 \(a_x\) 连到一起,这样我们就可以连接 \(a_y\to b_y\)。
显然只有这 \(5\) 种情况最优,并且不难看出我们可以维护 \(a,b\) 都没有选过的位置 \(x\) 中 \(a_x+b_x\) 最大的 \(x\)、当前 \(a\) 没有选过的位置 \(x\) 中 \(a_x\) 最大的 \(x\)、当前 \(b\) 没有选过的位置 \(x\) 中 \(b_x\) 最大的 \(x\)、当前 \(a\) 没有选过但是 \(b\) 选过的位置 \(x\) 中 \(a_x\) 最大的 \(x\)、当前 \(b\) 没有选过但是 \(a\) 选过的位置 \(x\) 中 \(b_x\) 最大的 \(x\) 全部用优先队列维护出来。那么单次增广只需要在这 \(5\) 中情况中找最优即可,复杂度是 \(O(n\log n)\) 的,这个过程实质上是模拟费用流(反悔贪心)。