2026.9 图论专题做题记录
CF547D Mike and Fish
将横纵坐标看成两排点,记第 \(x=i\) 为 \(i_x\),第 \(y=i\) 为 \(i_y\)。
那么 \(i_{x}\) 和 \(i_y\) 连边后得到二分图。给二分图边黑白染色,使得每个点的连边中黑白点数量差不超过 \(1\)。
注意到一个奇数度数的点黑白点数量差一定为 \(1\)。考虑建一个虚点来平衡度数。将所有奇数度数的点和这个虚点连一条边,那么所有点的度数都变成偶数了。
这样可以跑从虚点出发的欧拉回路,对于构造,所有左部点走向右部点为黑;右部点走向左部点为白。考虑证明合法性:
- 如果一个点度数是偶数。根据欧拉回路,一定有一半回一半出。黑白数量相同。
- 如果一个点度数是奇数。同理,算上与虚点的边后一定有一半回一半出。又因为和虚点的边不染色,所以黑白数量差 \(1\)。
时间复杂度 \(O(n)\)。
P15869 【MX-X26-T5】「Cfz Round 7」anybody can finds love (expect you)
考虑给每个点的所有边两两配对,表示只要这次是从其中一个进来或出去的,那么下一步就要从另一个出去或进来。
那么只要一个点所有边对应点不存在绝对众数就一定可以这么配对,同时如果存在绝对众数一定无解。
考虑构造,DFS 的时候存 \((u,pre)\) 表示当前点与上一次经过多边。首先如果 \(pre\) 对应的配对边没有走过,那么强制下一步走配对边出去。对于剩下的配对边,由于这些配对边对应点两两不同,所以一定有一个和 \(pre\) 这条边对应的点不同,先走那个就行了。
复杂度 \(O(n+m)\) 或 \(O((n+m)\log n)\)。
AT_agc018_f [AGC018F] Two Trees
首先不难注意到对于任意一个点 \(u\),若其在两棵树中儿子数量奇偶性不同,则一定无解。
先建个虚点把两棵树连起来(和树根连边)。考虑对于一个奇数度数的点 \(i\),将其在两棵树中连起来。
那么所有点的度数都是偶数了。
跑一遍欧拉回路,构造:
- 这条边为 \(T_1\) 中的边或 \(T_2\) 中的边。不管。
- 这条边从 \(T_1\) 到 \(T_2\)。将这个点点权设为 \(1\)。
- 这条边从 \(T_2\) 到 \(T_1\)。将这个点点权设为 \(-1\)。
考虑证明其合法性。将欧拉回路拆成若干个环。对 \(T_1\) 中的点 \(u\) 的所有边分类讨论:
- \(u\) 先走到某个儿子,最后走到 \(T_2\) 中的 \(u\) 或 \(u\) 的某个儿子返回。注意到这样从子树中某个点走到 \(T_2\) 会贡献 \(1\),从 \(T_2\) 回到子树某个点会贡献 \(-1\)。所以整体贡献 \(0\)。
- \(u\) 先走到某个儿子,最后走到 \(u\) 的父亲返回。此时只会贡献 \(1\)。
- \(u\) 先走到 \(T_2\) 中的 \(u\),最后走到 \(u\) 的父亲返回。同样只会贡献 \(1\)。
- \(u\) 先走到 \(u\) 的父亲,最后走到 \(T_2\) 中的 \(u\) 返回,此时只会贡献 \(-1\)。
由于父亲边只能走一次,所以恰好贡献绝对值为 \(1\)。对 \(T_2\) 中的 \(u\) 同理。
时间复杂度 \(O(n)\)。
P3275 [SCOI2011] 糖果
直接差分约束做。
P11095 [ROI 2021] 旅行 (Day 2)
考虑枚举 \(t_{max}\)。把最小生成树建出来。
加入一条边 \((u,v,t_{max})\):
- 是最小生成树上的边。设 \(u\) 深度较小。
- 维护 \(f_x\) 为 \(x\) 到 \(1\) 边权最小值,将 \(v\) 子树中所有点的 \(f_x\) 对 \(t_{max}\) 取 \(\min\)(初始化 \(+\infin\))。
- 不是最小生成树上的边,此时会形成边双。注意到一个边双中的边都是可以经过的。所以考虑将 \(P(u,v)\) 中所有边双合并,其中 \(P(u,v)\) 为树上 \(u\) 到 \(v\) 的路径。
- 维护 \(g_x\) 为与 \(x\) 在一个边双且深度最小的祖先,\(h_x\) 为 \(x\) 所在边双边权最小值。记 \(w\) 为 \(\text{lca}(u,v)\) 所在连通块。那么分别从 \(u,v\) 开始跳,每次跳到 \(fa_{g_x}\),并维护一路上 \(h_x\) 与 \(t(g_x,fa_{g_x})\) 的最小值,直到跳到 \(g_x = w\)。最后将一路上所有点的 \(g\) 合并成 \(w\),并将 \(h_w\) 更新。显然,跳一次就会合并一次,所以均摊 \(O(n)\)。
- 将 \(w\) 子树中所有点的 \(f_x\) 对 \(h_w\) 取 \(\min\)。
- 维护 \(ans_x\) 为 \(x\) 的答案,将 \(w\) 子树中所有点的 \(ans_x\) 对 \(h_w + t_{max}\) 取 \(\min\)(初始化 \(+\infin\))。
再考虑一个点的真实答案。注意到 \(x\) 和 \(1\) 联通之前 \(ans_x\) 都是假的,所以维护一下每个点和 \(1\) 联通的时间,在枚举到这个时间时将 \(ans_x\) 改成 \(f_x + t_{max}\) 即可。
时间复杂度 \(O(n\log n)\)。线段树需要维护区间取 \(\min\),单点查询,单点修改。
P4630 [APIO2018] 铁人两项
考虑如果 \(s,f\) 确定,\(c\) 有多少种选法。显然 \(c\) 的数量等于 \(s\) 到 \(f\) 所有简单路径并的大小减 \(2\)。
由一个点双中任意 \(3\) 点 \(x,y,z\) 都存在 \(x\) 到 \(y\) 到 \(z\) 的路径得知,\(s\) 到 \(f\) 所有简单路径并等价于 \(s\) 到 \(f\) 所有点双并。
把圆方树建出来,那么这个并的大小减去 \(2\) 的值就等于将方点权值设为点双大小,园点权值设为 \(-1\) 后 \(s\) 到 \(f\) 路径权值和。
DFS 一遍,在 \(\text{lca}\) 处统计即可。时间复杂度 \(O(n + m)\)。
P6378 [PA 2010] Riddle
考虑 2-SAT。
记 \(c_i\) 为第 \(i\) 个点所属部分的编号。记 \(i_0\) 为不选 \(i\),\(i_1\) 为选 \(i\)。
对于一条边 \((u,v)\),\(u_0\) 向 \(v_1\) 连,\(v_0\) 向 \(u_0\) 连,得到至少选一个的限制。
对于一个部分 \(i\),记其点集为 \(S\)。那么一个 \(x\in S\) 需要 \(x_1\) 向 \(y\in S\land y\ne x\) 的 \(y_0\) 连,得到不能选两个以上的限制。这个前缀、后缀优化一下连边就行了。
直接对这个跑一遍 2-SAT。对于第 \(i\) 个部分:
- \(c_x = i\) 中选择的点数量不小于 \(2\)。由上面的连边方式得知不可能存在。
- \(c_x = i\) 中选择的点数量等于 \(1\)。合法。
- \(c_x = i\) 中选择的点数量等于 \(0\)。说明对于所有 \(c_u = i\) 的 \((u,v)\) 都满足 \(c_v \ne i\)。因为如果 \(c_v = i\) 显然不满足至少选一个的限制。那么此时任意再选一个 \(c_u = i\) 的点也是可以的。所以合法。
时间复杂度 \(O(n+m)\)。
P5332 [JSOI2019] 精准预测
只保留有用的点,即预测中 \(2m\) 个点和最后 \(T+1\) 时刻的 \(n\) 个点。
用 2-SAT 跑一遍后一个点的答案就等价于 \(n-1\) 减去它能到达的 \((y,T+1,0)\)(即推出死亡的点)。
缩点之后就是一个 DAG 可达性统计。复杂度 \(O(\frac{nm}{\omega})\)。
QOJ10706 Red-Blue MST
考虑先将最小生成树建出来。考虑一个不在最小生成树上的红边,容易得知,它如果要替换一条蓝边,那么这条蓝边应该满足:
- 将所有边权比该红边小的红边,边权比该蓝边小的蓝边,最小生成树上的红边连起来后,该红边 \((u,v)\) 两点不联通。且加入该蓝边后 \((u,v)\) 联通。
那么直接对这个做整体二分。时间复杂度 \(O(n\log^2 n)\),要可撤销并查集。
P6643 [CCO 2020] Mountains and Valleys
注意到非树边最多走一条,证明简单。
考虑枚举起点 \(s\),终点 \(t\) 和这条非树边 \((u,v,w)\)。记 \(p(u,v)\) 为 \(u\) 到 \(v\) 简单路径经过的边集。
容易发现,这样的代价就是 \(2(n-1)-\text{dis}(s,t) -\text{dis}(u,v) + w +2\max(0,|p(u,v)\cap p(s,t)|-1)\)。也就是从 \(s\) 走到某个点 \(x\),再走到 \(u\),经过非树边到 \(v\),再走到某个点 \(y\),然后返回去把 \(p(x,y)\) 连接的点走完,最后走到 \(t\)(不重要的边显然都会经过两次,不必在意)。
考虑点分治维护这个东西。那么我们只需要对经过分治中心的非树边 \((u,v)\)(因为如果在同一个子树内,在之后的分治一定会算到)。
简单 DP 算一下就可以做到 \(O(siz)\)。
由于最多分治两层,所以整体 \(O(n+m)\)。
P10357 [PA 2024] Żelki
考虑先背包求出 \(f_{x}\) 为每种颜色选择一个,使得重量和对 \(m\) 取模的结果为 \(x\) 时的最小花费。这个的时间复杂度 \(O(nm)\)。
然后就变成同余最短路了。\(i\) 向 \((i+j)\bmod m\) 连边权为 \(f_{j}\) 的边,则对于 \(r\) 的答案就等于从 \(0\) 走到 \(r\) 的最短路。由于 \(|E| = |V|^2\),所以跑 dij 的时间复杂度 \(O(m^2)\)。
整体时间复杂度 \(O(nm+m^2)\)。
AT_arc076_d [ARC076F] Exhausted?
有 Hall 定义得知,最大匹配等于左部点数减去 \(\max(|S|-|N(S)|)\)。
对于这题,答案显然就是没有匹配的左部点数量,即 \(\max(0,\max(|S|-|N(S)|))\)。
如果已知 \(S\),注意到 \(N(S) = [1,\max\limits_{x\in S}^{}L_x]\cup [\min\limits_{x\in S}^{}R_x,m]\)。所以 \(|S| - |N(S)| =|S| - m+(\min\limits_{x\in S}^{}R_x - \max\limits_{x\in S}^{}L_x -1)\)。
将区间按照 \(R_i\) 从大到小排序,扫 \(R\),维护 \(f_{L}\) 表示 \(\max\limits_{x\in S}^{}L_x = L\) 时,\(|S|-L\) 的最大值。那么加入一个区间 \([L_i,R_i]\) 时:
- 对 \(L \ge L_i\),将 \(f_L\) 增加 \(1\)。
- 更新答案 \(ans\gets \max(ans,(\max f_L) -m+ R_i-1)\)。
初始化 \(f_L = -L\)。
线段树做到 \(O(n\log n)\)。
P7816 「Stoi2029」以父之名
P15869 + CF547D 属于是。
考虑一个点的所有边两两配对。显然尽量 \((2,2),(1,1)\) 配对就这么配。最后只会是剩下一个 \(1\) 或剩下 \((2,1)\)。前一种情况的点用一个大虚点连起来让它们度数变成偶数,后一种直接配对。
最后跑一遍欧拉回路,怎么走的边就怎么定向。时间复杂度 \(O(n+m)\)。
P13592 [NWRRC 2023] Loops
注意到对于每一行的点,可以钦定其值是单调递增的,因为这三种图每个都存在一组构造,使得第一行两个数单增且第二行两个数单增。
容易发现,此时如果给第一列确定一个顺序,后面每个 \(2\times 2\) 的图边的顺序都是唯一确定的。不妨设第一列从上往下是单增的。那么就可以 \(O(nm)\) 得到大小关系了。
显然这么做完之后不会有环,跑拓扑排序即可。时间复杂度 \(O(nm)\)。
CF2061G Kevin and Teams
注意到 \(k = \lfloor\frac{n+1}{3}\rfloor\)。
证明考虑构造一个前 \(m\) 个点为完全图,剩下点为孤立点的图。那么该图的匹配数量为 \(\lfloor\frac{m}{2}\rfloor\),补图的匹配数量为 \(\min(n-m,m)+\lfloor\frac{n-2m}{2}\rfloor\)。不难得之 \(\max\limits_{m}\max(\lfloor\frac{m}{2}\rfloor,\min(n-m,m)+\lfloor\frac{n-2m}{2}\rfloor) = \lfloor\frac{n+1}{3}\rfloor\)。
对于构造,考虑将是朋友看成黑边,不是朋友看成白边。维护一个同色的链,每次查询一个点 \(i\) 和当前链尾的点。
- 若得到的颜色相同。连在链尾后面。
- 若得到的颜色不同。设链尾上一个点为 \(x\),链尾为 \(y\)。将 \((x,y),(y,i)\) 分别加入两种颜色的答案集合,并删去 \(x,y\) 两点。
这样的话一次情况 \(2\) 会消耗 \(3\) 个点,并将两种颜色集合的答案增加 \(1\)。设最终链上有 \(x\) 个点,那么选择与这条链颜色相同的答案集合作为最终答案,并把链上相邻两个当作一组,可以得到 \(k=\lfloor\frac{x}{2}\rfloor+\frac{n-x}{3}\ge \lfloor\frac{n+1}{3}\rfloor\)。
时间复杂度 \(O(n)\)。
AT_agc036_d [AGC036D] Negative Cycle
对于边,分 \(3\) 种情况:
- \(j = i + 1\)。\(i\to j\) 边权为 \(0\)。
- \(j>i\)。\(i\to j\) 边权为 \(-1\)。
- \(j<i\)。\(i\to j\) 边权为 \(1\)。
不难发现,这个等价于对于一个数组 \(x_{0\sim n-1}\),有限制:
- \(x_{i}+(0)\ge x_{i+1}\)。
- 对于 \(j>i\),\(x_i+(-1) \ge x_j\)。
- 对于 \(j<i\),\(x_i+(1) \ge x_j\)。
要求 \(x_{0\sim n-1}\) 有解。
把 \(x_{0\sim n-1}\) 看成前缀和,那么等价于:
- \(a_i \le 0\)。
- 对于边权为 \(-1\) 的边 \(i\to j\),\(\sum\limits_{x=i+1}^{j}a_x \le -1\)。
- 对于边权为 \(1\) 的边 \(i\to j\),\(\sum\limits_{x=j+1}^{i}a_x \ge -1\)。
整体取个反,相当于:
- \(a_i \in \{0,1\}\)。
- 对于边权为 \(-1\) 的边 \(i\to j\),\([i+1,j]\) 中至少 \(1\) 个 \(1\)。
- 对于边权为 \(1\) 的边 \(i\to j\),\([j+1,i]\) 中最多 \(1\) 个 \(1\)。
要求 \(a_{0\sim n-1}\) 有解。
定义状态函数 \(f_{i,j,k}\) 为前 \(i\) 个下标,最后一个 \(1\) 在 \(j\),倒数第二个 \(1\) 在 \(k\) 的最小代价。那么可以知道,对于右端点为 \(i\) 的区间 \([l,i]\),应该满足:
- \(l\in [1,k]\)。区间 \([l,i]\) 中有至少 \(2\) 个 \(1\)。此时所有 \(v+1 \in [1,k],u=i\) 的边 \(u\to v\) 应该删掉。
- \(l\in [k+1,j]\)。区间 \([l,i]\) 中恰好有 \(1\) 个 \(1\)。任意限制都满足。
- \(l\in [j+1,i]\)。区间 \([l,i]\) 中没有 \(1\)。此时所有 \(u+1\in [j+1,i],v=i\) 的边 \(u\to v\) 应该删掉。
维护两种限制的前缀和,可以 \(O(1)\) 得到需要删掉的边的代价和,记为 \(w(j,k,i)\)。那么转移为:
- \(f_{i,j,k}=f_{i-1,j,k}\)。
- \(f_{i,i,j}=\min\limits_{k\le j}^{}f_{i-1,j,k}\)。
- \(f_{i,j,k}\gets f_{i,j,k}+w(j,k,i)\)。
初始化 \(f_{0,0,0}=0\),答案为 \(\min f_{n,j,k}\)。时间复杂度 \(O(n^3)\)。
P13358 [GDCPC 2024] 小班课
结论:
如果按照意向度从高到低的优先级跑匈牙利,那么一定存在一个点 \(x\),使得 \(x\) 匹配到了他意向度最高的点。
证明:
考虑反证。假设不存在这样的点 \(x\),那么匹配方式一定形如:\(x_1\to c_1\to x_2\to c_2\dots\to x_k\to c_k\to x_1\)。其中 \(x_i\) 为左部点,\(c_i\) 为 \(x_i\) 意向度最高的点,\(c_i\to x_{i+1}\) 为实际上这个右部点匹配的左部点。
不妨设当前尝试匹配的点为 \(x_1\)。
由于 \(c_1\) 是 \(x_1\) 意向度最高的点,所以在增广 \(x_k\) 时如果 \(c_k\) 被 \(x_1\) 选择了,说明之前 \(x_1\) 尝试匹配 \(c_1\) 就已经失败了。此时不可能 \(x_1\) 在已经匹配了 \(c_k\) 的情况下又来尝试匹配 \(c_1\)。故不存在这种情况。
有这个结论,不难发现答案就等于最大匹配。
这样每次跑最大匹配,然后选一个可以的点复杂度是 \(O(n^4)\) 的。
考虑随便跑一个最大匹配然后调整。
对于每个 \(i\),设其意向度最高的点为 \(c_i\) 且 \(c_i\) 被 \(x_i\) 匹配了。$i $ 向 \(x_i\) 连边。得到的是内向基环树森林。
发现对于一个环 \(x_1\to x_2\dots \to x_k \to x_1\),可以直接让他们匹配到自已意向度最高的点 \(c_{x_i}\)(相当于是整体右移一步)。这样整个环就都消去了。
之后再这样连边,就又是很多基环树。
显然最后一定能消完。复杂度 \(O(n^3)\)。

浙公网安备 33010602011771号