2025.5
* P4208 [JSOI2008] 最小生成树计数
Proof 1
对于两个不同的 MST,把相同的边消掉,发现在不同的边中,边权最小的一定是两边都有,于是可以构造更小的生成树,矛盾。
Proof 2
考虑在 Kruskal 中每次加入相同边权,消去简单环上。容易发现这个过程每个边权的边数都相等。
于是所有 MST 在每个边权下边的数量相等。
跑一遍 Kruskal 记录 MST 每个边权的边数。
因为不能维护在每个边权下选一定数量边的限制,不能直接矩阵树定理。
考虑如何利用 具有相同权值的边不会超过 10 条。
由 Proof 2,易知每个边权不仅数量相等,而且连通情况相同。
Sol 1
对每种权值 \(x\) 单独考虑,边权为 \(1\sim x-1\) 的连通情况相同,那么先连起来。
对于这个权值暴力算,维护一个带撤销并查集。
\(O(2^{10}m)\)
Sol 2
还是对每种权值 \(x\) 单独考虑,由连通情况相同,考虑把其他权值在 MST 上的边连起来缩点,然后跑矩阵树定理。
设这个权值的边要选 \(c_x\) 条,则形成 \(c_x+1\) 个连通块。
矩阵树定理 \(c_x^3\)。
\(O(n^3)\)
考虑处理模数不为质数,考虑对行整体进行辗转相除法。
\(O(n^3\log{n})\)
单独对要消的元素辗转相除,假设原来是 \(a, b\),变成 \(k_1a+k_2b,k_3a+k_4b\),直接做即可。
\(O(n^3)\)
LOJ10111 相框
不妨先做操作 \(2\),再做操作 \(1\)。
操作 \(2\) 要求两边都是自由端,但我们可以改一下,在操作 \(2\) 时烧熔焊点,则满足自由端。把操作 \(1\) 提前,变为任意两端都可以合并。
有欧拉回路即可构造。
操作 \(2\) 的贡献为所有度数大于 \(2\) 的焊点数量。
欧拉回路的条件是把全图连同,且度数为偶数。
不妨把自由端也建点,于是变为操作 \(1\) 变为合并点。
分不存在奇度数的点的连通块集合 \(\mathrm{evenscc}\) 和存在奇度数的点的联通块集合 \(\mathrm{oddscc}\)。
不妨先用 \(|\mathrm{evenscc}|\) 的代价将所有 \(\mathrm{evenscc}\) 与任意 \(x\in \mathrm{oddscc}\) 连接,奇度数不变。
剩下的奇度数点两两连接即可,且存在某种方式使得所有 \(\mathrm{oddscc}\) 联通。
即是说,所有连通块连成一条链,则需要所有奇数点数除以 \(2\) 的代价,另外有一条链连接 \(\mathrm{evenscc}\)。操作 \(2\) 的贡献为所有度数大于 \(2\) 的焊点数量。于是某个 \(x\in \mathrm{evenscc}\) 只有度数为 \(2\) 的点,则需要使用一次操作 \(2\)。
P9178 [COCI 2022/2023 #5] Diskurs
考虑对每个数字 \(x\) 连边 \(x\overset{1}{\to} x \ \mathrm{xor}\ 2 ^ i (0\le i\lt m)\)。
但有个问题,如果跑最长路,就会死循环。
考虑容斥。汉明距离等于 \(m\) 减去取反后的最小汉明距离。
那么只需要找所有给定点到 \(\overline{x}\) 的最短距离。
可以用 BFS 或状压 dp 实现。
状压 dp 的转移顺序,考虑先枚举转移边,再枚举点,可以证明这是一个合法的顺序。
P5019 [NOIP 2018 提高组] 铺设道路
P12147 【MX-X11-T1】「蓬莱人形 Round 1」仅此而已,就已经足够了
注意到问题可以归约到 \(k = 0\) 的情形。
把贡献相同的一起计算。发现贡献相同的都从第 \(k\) 位有相等长度的 \((11\cdots10)_2\)。
枚举这个东西,然后计算 \(1\sim n\) 有多少个数有这样的特征。
P1875 佳佳的魔法药水
考虑 dp。发现会出现环。
Sol 1
考虑代价都是正的,Dijkstra 的一种转移序。
每次确定花费最小的,然后松弛。
当 \(x\) 松弛时,假设 \(x, y\) 可以合出 \(z\)。钦定转移顺序,要求 \(y\) 已确定,\(z\) 未确定。
这样可以唯一转移,而且应该这样。
对于 \(A + A\to C\) 的,方案是 \(\dfrac{cnt_A(cnt_A+1)}{2}\),但是正解却考虑了合成 \(A\) 和购买 \(A\) 的顺序。
Sol 2
SPFA 迭代后,在转移 DAG 上求方案数。
同类的题还有 P4042 [AHOI2014/JSOI2014] 骑士游戏。
这题是 \(1\) 分裂为 \(n\),但是一个怪兽只有一种合成方式。
实现比较神奇。
令 \(\mathrm{dis}_u\) 在 \(\mathrm{vis}_u = 0\) 时,表示用普通攻击打 \(u\) 的最小代价是多少;\(\mathrm{vis}_u = 1\) 时,表示最优解。
最初在堆里放魔法攻击的,取出 \(u\),则确定 \(u\) 的最优解,然后更新 \(u\) 能合成的怪物 \(v\),\(\mathrm{dis}_v\gets \mathrm{dis}_v + \mathrm{dis}_u\),当 \(\mathrm{R}_v\gets \mathrm{R}_v - 1\) 后等于 \(0\),则得到普通攻击打 \(v\) 的最小花费,放进堆里。
当然,这道题还可以用 SPFA。
P12000 扶苏出勤日记
不太好 dp,因为 dp 需要消除后效性,则需要把游戏币加入状态。
考虑贪心。
答案具有单调性,考虑二分。
设 \(\mathrm{rn}_i\) 为 \(a_j\gt a_i,j\gt i\) 的最小的 \(j\)。
在 \([i,\mathrm{rn}_i-1]\) 的在 \(i\) 买最优。
当前币够用了,就直接用。否则在 \(i\) 买。
P2761 软件补丁问题
状态压缩,最短路。
P2513 [HAOI2009] 逆序对数列
定义 \(f_{i, j}\) 为 \([1, i]\) 的排列逆序对为 \(j\) 的排列数量。
前缀和优化。
P1990 覆盖墙壁
定义 \(f_{i, 0/1, 0/1}\) 表示前 \(i\) 列,前 \(i - 1\) 列都覆盖了,\((1, i), (2, i)\) 是否覆盖的方案数。
但很多都重复了。
考虑定义 \(f_i\) 为覆盖前 \(i\) 列的方案数,\(g_i\) 为覆盖前 \(i - 1\) 列,第 \(i\) 列只覆盖一个格子的方案数。
B4309 [蓝桥杯青少年组国赛 2024] 第四题
贪心题。
若有两个及以上连通块,则为 \(0\)。
否则,
若连通块大小小于等于 \(2\),则为 \(-1\)。
否则,
若存在一个棋子周围只有 \(1\) 个棋子,则为 \(1\)。
否则为 \(2\)。
P12368 [蓝桥杯 2022 省 Python B] 消除游戏
设有 \(c\) 个字符段,每个字符段平均长度为 \(k\)。
若暴力模拟,一次复杂度为 \(ck\),一共有 \(k\) 次,总复杂度为 \(O(ck^2)\)。
\(s\) 表示每段的字符,\(c\) 表示每段的大小,用 \((s, c)\) 这样的二元组表示。
\(\text{edda}\) 表示为 \((e, 1), (d, 2), (a, 1)\)。
设当前二元组为 \((s_i,c_i)\)。
若 \(c_{i-1}\gt 1 \vee c_i\gt 1\),则 \(i\) 的左端点是边缘字符。
右端点同理。
则每次模拟是 \(O(c)\) 的,总复杂度为 \(O(ck) = O(n)\)。
P4011 孤岛营救问题
状压 + 最短路。
P3355 骑士共存问题
就是一个最大独立集问题。
考虑分左部点和右部点。
这类题有个常用的划分方式:按 \(i+j\) 的奇偶性划分为 \(X, Y\)。
\(S\overset{1}{\to} X, Y\overset{1}{\to} T,X\overset{1/+\infty}{\to} Y\)
当 \(X\to Y\) 的容量设置为 \(1\),就是二分图的最大流
当设置为 \(+\infty\),
最大独立集 = 总点数 - 最大流 = 总点数 - 最小割
选 \(S\cap X\) 和 \(T\cap Y\) 的点,而切的边所对应的点,就是丢掉的点。
要最少,即为最小割。
P2045 方格取数加强版
取 \(2\) 次是 dp。
取 \(k\) 次是网络流。
接下来要解决一些问题。
- 走过了,就没有数了。
- 走过了,但是还可以走,只是没有数。
- 恰走 \(k\) 次。
于是到 \((x,y)\) 有 \(2\) 种。
第一种,可以取数,容量为 \(1\),表示仅取一次,费用为 \(A_{x,y}\),表示取数。
第二种,没有数取,容量为 \(+\infty\),费用为 \(0\)。
注意到,这个边容量实际上是在点上的,于是拆点。
对每个点 \((x, y)\) 拆为 \(in_{x,y}, out_{x,y}\)。
重新理建边。
\(out_u\to in_{x,y}\):容量 \(+\infty\),费用 \(0\)。
\(in_{x,y}\to out_{x,y}\):容量 \(1\),费用 \(A_{x, y}\),表示取数。
\(in_{x,y}\to out_{x,y}\):容量 \(+\infty\),费用 \(0\),表示跳过。
这还可以表示,在路径上选择是否取数,而非全取。因为费用为正,一定会取。
考虑源汇,
\(S\to in_{1,1}\):容量 \(k\),费用 \(0\)。(也可以把 \(in_{1,1}\) 当 \(S\),改下流量即可。)
\(T=out_{n,n}\)
跑最大费用最大流
* P3358 最长 k 可重区间集问题
给定 \(n\) 个开区间,选出一些区间,求在满足覆盖任意一点的开区间数量不超过 \(k\) 的条件下,选出区间的长度和的最大值。
"不超过 \(k\)"、每个区间只能选一次,容易想到把区间覆盖次数当作流。
"最大值":把区间长度作为费用。
还有一个问题我们要跑整的区间,而不是跑子区间。这个通过钦定流进入、出去实直线上的点解决。
那么考虑建边,
一个错误的解法,
实直线上,\(x\to x+1\),容量 \(k\),费用 \(1\)。
\(S\to l_i\):容量 \(1\),费用 \(0\)。
\(r_i\to T\):容量 \(1\),费用 \(0\)。
这个存在 \(S\to l_i \to r_j\to T\) 的情况。
为了 \(l_i, r_i\) 一一配对,不把费用摊在实直线上。
注意到,\(l_i\to r_i\) 这样连是很难表示有交的覆盖。
题解中提到了从 \(k\) 中剥离的做法。
把没有交的区间看成串联,有交的区间看成并联。相当于 \(k\) 次串联,则每个点一定不会覆盖超过 \(k\) 次。
跑最大费用最大流
有两篇比较好的题解:Link 1、Link 2。
P3356 火星探险问题
在 P2045 的基础上输出方案。
对流过的路径建图,然后 dfs 输出。
P3357 最长k可重线段集问题
与 P3358 相同。
注意端点转化。
先扩域到 \(2\) 倍。
若 \(x_0 = x_1\),则 \(x_1\gets x_1+1\)。
否则,\(x_0\gets x_0+1\)。
P4012 深海机器人问题
做法同方格取数。
P4013 数字梯形问题
做法同方格取数。
P1031 [NOIP 2002 提高组] 均分纸牌
引理 1
最优解不存在相邻的两堆互相给。
Proof
可以约掉。
引理 2
答案最多为 \(n - 1\)。
由引理 1 易证。
最优解连边后是多个 DAG。
不考虑方向,只考虑的边的数量。
考虑从 \(1\) 到 \(n\) 做。
前 \(1\sim i - 1\) 都处理完了。
若 \(i\) 多了,给 \(i + 1\);少了,从 \(i + 1\) 拿。
若拿出负数,一定可以通过调整拿的顺序,使得答案为正。
Sol 1
模拟
Sol 2
设 \(\mathrm{ave}\) 是平均数,\(s_i\) 是 \(a_i - \mathrm{ave}\) 的前缀和。
若前 \(k\) 个人的和是 \(\mathrm{ave}\) 的倍数,则前 \(k\) 个人的最优解是 \(\sum_{j=1}^{k}|s_j|\)。
P4016 负载平衡问题(环形)
注意到,\(i, i + 1\) 不同时存在相邻交换和绕一圈交换,显然不优。
于是必定存在一对相邻的不交换。
断环为链,做一遍序列上的即可。
设断开的位置为 \(k, k + 1\),则此时最优解为 \(\sum_{i = 1}^{n}|s_i - s_k|\)。
当取中位数最优。
P2756 飞行员配对方案问题
板子。
P2763 试题库问题
可以用最大流做。
也可以用匈牙利算法。
对于一个题号,要多少个就拆多少个点。跑最大匹配。
P3254 圆桌问题
很直观的建图。
P4014 分配问题
二分图最大权匹配。
P4015 运输问题
同 P4014。
P2765 魔术球问题
若 \(x + y\) 是完全平方数,且 \(x\ge y\),建边 \(x\to y\)。
把一个数拆成左部点和右部点。
从左部点出发,走交错路,即为表示一根柱子上的情况。
问题转化为 对于给定的 \(n\),计算不超过 \(n\) 条路径最多可以覆盖多少满足条件的节点。
最小路径覆盖 = 原图的结点数 - 新图的最大匹配数。
每次加一个点后,连上它的边,然后在残量网络上跑。
P2764 最小路径覆盖问题
把一个点 \(x\) 拆成左部点 \(x_1\) 和右部点 \(x_2\)。
对于 \(u\to v\),连边 \(u_1\to v_2\)。
输出方案同上一题。
P2766 最长不下降子序列问题
难点在于如何每次都保证选长度为 \(s\) 的不下降子序列。
先求出 \(f_i\)。
因为每个点只能用一次,所以拆点。
若 \(f_i = 1\),则为起始点。
若 \(f_i = s\),则为终止点。
若 \(f_i + 1 = f_j (i\lt j)\),则连边 \(i\to j\)。
第三问,把 \(1, n\) 的容量改一下即可。
特判 \(s = 1\)。
P2770 航空路线问题
对限制,拆点。
跑费用流。
P1251 餐巾计划问题
考虑处理一些操作。
- 买
- 快洗
- 慢洗
- 延期洗
一天应该是先买,然后抉择旧餐巾的去处。
由于 \(4\),则一天接收到的餐巾有两种。
不妨拆点 \(i\) 为 \(\mathrm{st}_i,\mathrm{ed}_i\)。
Sol 1
(没说的边的容量都是 \(+\infty\))
买,\(S\to \mathrm{st}_i\),费用 \(p\)。
快洗,\(\mathrm{ed}_i\) 连向 \(\mathrm{st}_{i+m}\),费用 \(f\)。
慢洗同理。
延期洗,\(\mathrm{ed}_i\) 连向 \(\mathrm{ed}_{i+1}\),费用为 \(0\)。
\(\mathrm{st}_i\) 连向 \(\mathrm{st}_{i+1}\),费用为 \(0\)。
\(\mathrm{st}_i\to \mathrm{ed}_i\),容量 \(r_i\),费用 \(0\)。
\(\mathrm{ed}_n\to T\),费用 \(0\)。
要求所有 \(\mathrm{st}_i\to \mathrm{ed}_i\) 满流,则改费用为 \(-\infty\)。
跑费用流。
答案需要加上 \(\infty\times\sum_{i=}^{n}r_i\)。
Sol 2
四个操作连边与上面相同。
考虑源点汇点的连边。
网络流的建图一定有顺序的,建的边一定是沿源点流向汇点,否则图就会不流通。
于是源点连向 \(\mathrm{ed}_i\),表示每天获得 \(r_i\) 块旧餐巾。
\(\mathrm{st}_i\) 连向汇点,表示每天用 \(r_i\) 块新餐巾。
跑最小费用最大流。
P2754 [CTSC1999] 家园 / 星际转移问题(分层图最大流)
啊,刚开始就没想对啊。
并查集判无解。
考虑到每个时刻,飞船位置都不同。
考虑状态为 \((i, t)\),表示时间为 \(t\) 时,在 \(i\) 站。
刚开始想的是,建的 \(t\) 最大为 \(\mathrm{lcm} \ r_i\) 就循环了。
事实也确实如此。
但是,一个关键的问题是,网络流增广只能是简单路径,且这样就不能表示飞船载人的限制。
考虑枚举答案 \(t\),则建 \(t + 1\) 层图。也可以二分,但是枚举可以在残留网络上跑。
最大点数大概为 \(O(n^3k)\)。
P4009 汽车加油行驶问题
Sol 1
分层图最短路。
Sol 2
实际上,跑最大流为 \(1\) 的最小费用最大流即可。
P2762 太空飞行计划问题
可以转成同号的最大最小,用最小割。
P2774 方格取数问题
套路地按横纵坐标奇偶性分左右部点,做法与上题大同小异。

浙公网安备 33010602011771号