一类图上二选一构造问题
CF1198C Matching vs Independent Set
题目大意:
给定一张 (3cdot n) 个节点、(m) 条边,无自环、无重边的无向连通图。
定义一个匹配是一个边的集合,满足其中任意两条边没有公共端点。
定义一个独立集是一个点的集合,满足其中任意两个点没有边直接相连。
请你找出一个 (n) 条边的匹配,或一个 (n) 个点的独立集。
数据范围:(1leq nleq 10^5),(0leq mleq 5cdot 10^5)。
容易想到去求最大匹配。但是求一般图最大匹配的带花树算法时间复杂度是 (mathcal{O}(n^3)) 的。
考虑退而求其次,找出任意一个极大匹配。具体来说:我们每次取出一条边,并将它的两个端点删掉(一个点被删掉后,所有与它相连的边也被删掉),如此重复直到图上没有边为止。显然:
- 被我们取出的边,是一个匹配。因为一个点第一次被取到后,所有和它相连的边就都被删掉了,所以取出的边之间不会有公共点。
- 最终剩下的点,是一个独立集。首先,最终状态下,剩下的点之间肯定没有边(否则就还能继续取)。并且它们之间原来也不会有边,因为原图上的一条边,不会在两个端点都未被删除的情况下,平白无故消失。
考虑最终我们取出的边的数量,记为 (k)。
- 若 (k geq n),则我们已经找出了一个 (n) 条边的匹配。
- 若 (k < n),因为这 (k) 条边是匹配,所以没有公共端点,所以它们恰好占用了 (2k) 个点,所以还剩下 (3n - 2k geq n) 个点。这意味着我们找出了一个 (n) 个点的独立集。
综上所述,一定有解。
时间复杂度 (mathcal{O}(n + m))。
CF1364D Ehab's Last Corollary
题目大意:
给出一张 (n) 个点的无向连通图和一个常数 (k)。
你需要解决以下两个问题的任何一个:
- 找出一个大小为 (lceilfrac{k}{2} ceil) 的独立集。
- 找出一个大小不超过 (k) 的简单环。
独立集是一个点的集合,满足其中任意两点之间在原图上没有边直接相连。
可以证明这两个问题必然有一个可以被解决。
数据范围:(3leq kleq nleq10^5),(n - 1leq mleq 2cdot 10^5)(边数)。
以任意点为根,建出 DFS 树。如果我们将每条边按照第一次经过时的方向进行定向,则无向图的 DFS 树满足所有非树边都是后向边(即从一个节点连向其祖先的边)。
如果存在一条非树边 ((u, v))((v) 是 (u) 的祖先),满足 (mathrm{dep}(u) - mathrm{dep}(v) < k),则取 ((u, v)) 加上 (v) 到 (u) 的树上路径即为一个长度不超过 (k) 的简单环。
否则我们直接将节点按照深度的奇偶性划分为两个集合。在其中较大的一个集合里,把节点按 DFS 时访问的顺序排列,取任意连续的 (lceilfrac{k}{2} ceil) 个点,就是一个大小为 (lceilfrac{k}{2} ceil) 的独立集,证明如下:
- 首先根据鸽巢原理,这个“较大的集合”,大小一定大于等于 (lceilfrac{k}{2} ceil)。
- 下面证明它是独立集:
- 因为任意一条树边的两个端点,深度的奇偶性一定不同。所以上述做法得到的集合里,不存在两个点被树边相连。
- 对于一条非树边的两个端点 ((u, v))((v) 是 (u) 的祖先),设 (d = mathrm{dep}(u) - mathrm{dep}(v)),那么必有:(dgeq k)。把节点按 DFS 顺序排列后,(u, v) 之间至少有 (d + 1) 个点。如果想要同时取到 (u, v),就必须取至少 (lceilfrac{d + 1}{2} ceil) 个点。而我们只取了 (lceilfrac{k}{2} ceil) 个点。(k) 为奇数且 (d = k) 时,(u, v) 深度奇偶性不同,不会被同时取到;否则 (k) 为偶数或 (d > k),那么必有 (lceilfrac{d + 1}{2} ceil > lceilfrac{k}{2} ceil)。综上,(u, v) 不会被同时取到。
时间复杂度 (mathcal{O}(n + m))。
CF1325F Ehab's Last Theorem
题目大意:
给出一张 (n) 个点的无向连通图。
你需要解决以下两个问题的任何一个:
- 找出一个大小为 (lceilsqrt{n} ceil) 的独立集。
- 找出一个大小至少为 (lceilsqrt{n} ceil) 的简单环。
独立集是一个点的集合,满足其中任意两点之间在原图上没有边直接相连。
可以证明这两个问题必然有一个可以被解决。
数据范围:(5leq nleq10^5),(n - 1leq mleq 2cdot 10^5)(边数)。
设 (S = lceilsqrt{n} ceil)。显然 (S geq 3)。
以任意点为根,建出 DFS 树。如果我们将每条边按照第一次经过时的方向进行定向,则无向图的 DFS 树满足所有非树边都是后向边(即从一个节点连向其祖先的边)。
如果存在一条非树边 ((u, v))((v) 是 (u) 的祖先),满足 (mathrm{dep}(u) - mathrm{dep}(v) geq S - 1),则取 ((u, v)) 加上 (v) 到 (u) 的树上路径即为一个大小至少为 (S) 的简单环,可以完成任务 2。
否则,将节点按照深度 (mod (S - 1)) 的值,划分为 (S - 1) 类。此时,同一类节点如果是祖先 - 后代关系,那么它们在树上深度差至少为 (S - 1),因此同一类节点之间一定没有边相连。
根据鸽巢原理,至少有一类节点的数量 (geq lceilfrac{n}{S - 1} ceilgeq S),于是我们就找到了一个大小至少为 (S) 的独立集,任取其中 (S) 个节点,即可完成任务 1。
时间复杂度 (mathcal{O}(n + m))。
CF1391E Pairs of Pairs
题目大意:
给定一张 (n) 个节点、(m) 条边,无自环、无重边的无向连通图。
考虑将其中的一些节点配对,使得每个节点至多只出现在一对中。如果对于任意两对节点,这 (4) 个点的生成子图至多只有 (2) 条边,则称该配对方案是合法的。
你需要解决以下两个问题的任何一个:
- 找出一条包含至少 (lceilfrac{n}{2} ceil) 个节点的简单路径。
- 找出一组包含至少 (lceilfrac{n}{2} ceil) 个节点的合法的配对方案。
可以证明这两个问题必然有一个可以被解决。
数据范围:(2leq nleq 5cdot 10^5),(1leq mleq 10^6)。
设 (l = lceilfrac{n}{2} ceil)。
以任意点为根,建出 DFS 树。
定义一个节点的深度为,它到根路径上的点数。
设深度最大的点深度为 (d)。若 (d geq l),则直接取深度最大的点到根的路径,即可完成任务 1。
否则将节点按照深度分为 (d) 类。对于同一类点(也就是树上同一层里的点),记它们为 ({u_1, u_2, dots, u_k}),则依次配对:((u_1, u_2), (u_3, u_4), dots)。若本层里的点数 (k) 为偶数,则恰好配完,否则会浪费一个。因为层数 (dleq l - 1),所以最多只会浪费 (l - 1) 个,也就是用到的节点数量 (geq n - (l - 1)geq l)。
又因为无向图的 DFS 树上不存在横叉边,所以对于任意两对节点,这 (4) 个点的生成子图至多只有 (2) 条边。符合任务 2 的要求。
CF1439B Graph Subset Problem
题目大意:
给定一张 (n) 个点 (m) 条边的无自环、无重边无向图,以及一个正整数 (k)。
你需要解决以下两个问题的任何一个:
- 找出一个大小为 (k) 的团。也就是找出 (k) 个节点使得它们的生成子图是完全图。
- 找出一个子图,满足子图中任意节点都与至少 (k) 个同样在子图里的节点相连。
或者告知无解。
数据范围:(1leq n, m, kleq 10^5),(kleq n)。
开始时,把所有点丢到一个 ( exttt{set}) 里。以度数为关键字。支持:查询度数最小的点;修改一个点的度数(把原来的删除,再把新的插入)。然后执行如下过程:
- 取出度数最小的点 (u)。
- 如果它的度数 $ < k - 1$,显然它不可能被加入任何一种答案里,所以可以直接将这个点删除(同时与它相连的所有边也会被删除)。注意,删除 (u) 以后,其他与 (u) 有连边的点,度数可能会改变。回到步骤 1。
- 如果它的度数 $ = k - 1$。考虑 (u) 和它的 (k - 1) 个邻居,是否构成一个团。判断的方式就是暴力枚举 (frac{k(k - 1)}{2}) 条边,看它们是否都存在(判断一条边是否存在可以做到 (mathcal{O}(1)),见这篇文章)。如果是一个团,那么直接输出。否则点 (u) 就不可能出现在答案里了,将它删掉,回到步骤 1。
- 如果所有点的度数都 (geq k),那么整张图就是一个“满足第二种要求的子图”,直接作为答案输出即可。
在步骤 1 里,如果图为空(没有节点了),说明无解。
因为每次删掉的都是绝不可能出现在答案里的点,所以上述做法的正确性是显而易见的。
暴力判断一个团的时间复杂度是 (mathcal{O}(k^2)) 的,加起来是 (mathcal{O}(nk^2))。但是注意到,只有当 (frac{k(k - 1)}{2}leq m) 时,我们才需要判断。并且度数 (geq k - 1) 的点只有 (mathcal{O}(frac{m}{k})) 个,所以这部分的总复杂度是 (mathcal{O}(frac{m}{k}cdot k^2) = mathcal{O}(msqrt{m}))。
总时间复杂度 (mathcal{O}(nlog n + msqrt{m}))。
LOJ3113 「SDOI2019」热闹的聚会与尴尬的聚会
题目大意:
给定一张 (n) 个点 (m) 条边的简单无向图。请求出:
- 一个点集 (A)。设它的导出子图里,度数最小的点的度数为 (p)。
- 一个点集 (B),满足它是原图的一个独立集。设它的大小为 (q)。
点集 (A) 和 (B) 可以有交,也可以有节点不在任何一个点集里。
你需要构造出这样的两个点集,使得 (lfloorfrac{n}{p + 1} floor leq q) 且 (lfloorfrac{n}{q + 1} floor leq p)。
数据范围:(Tleq 32) 组测试数据。对于每组测试数据:(1leq nleq 10^4),(1leq mleq 10^5)。
条件可以改写成:((p + 1)(q + 1) > n)。因此显然是 (p, q) 越大越好。
因为两个点集互不影响,考虑独立地将它们构造出来。也就是把 (p, q) 分别最大化。
先考虑最大化 (p)。首先将所有点都放入点集,此时 (p) 就是图里度数最小的点的度数,记为 (p_t)。然后如果我们想要使 (p) 变得更大,则显然必须删去度数最小的点。将它删去后,其他点的度数也会相应地变化。我们不断重复此过程,直到图被删空为止。记下整个过程中 (p_t) 最大的时刻,将那一时刻的图作为第一个点集。
最大化 (q) 则比较困难。【一般图最大独立集】本身是没有多项式复杂度做法的。此时如果用模拟退火等随机化算法,强行求“最大独立集”,据说能得到不错的分数,因为题目给出的界其实很松。抛开随机,题目既然将两个问题放在一起,说明他们之间肯定有内在联系。于是结合上面的做法,去考虑求独立集。
上面的做法里,我们每次会删掉度数最小的点 (u)。并且在删之前的时刻,(p_t) 就等于 (u) 的度数。现在我们对该做法进行一点点修改:
- 仍然每次选出度数最小的点 (u)。
- 将 (u) 加入第二个点集。
- 将所有与 (u) 相邻的点从图上删去。
- 将点 (u) 从图上删去。
最后仍然取整个过程中 (p_t) 最大的时刻,将那一时刻的图作为第一个点集。但是注意,无论取了哪个时刻作为第一个点集,这将不会影响第二个点集的选取:在该时刻之后发生的、向第二个点集里加点的操作,仍然有效。步骤 3 保证了我们求出的第二个点集是独立集。
接下来问题的关键就是,这样求出的 (p, q) 是否满足大小的要求呢?
答案是肯定的。因为每当一个点 (u) 被加入独立集,它会同时删掉与它相邻的点,也就是删去的点数等于 (u) 的度数,等于彼时彼刻的 (p_t)。又因为最终作为答案的 (p) 是所有 (p_t) 里的最大值,所以每次被删除的点数都不超过 (p) 。所以独立集里的点数 (qgeq lceilfrac{n}{p + 1} ceil),所以 ((p + 1)(q + 1) > n)。
综上,我们构造出了符合所有要求的答案。
每次取度数最小的点,并支持修改一个点的度数,可以用线段树或 ( exttt{set}) 实现。时间复杂度 (mathcal{O}((n + m)log n))。
总结
在图上,题目问了你两个看似无关的问题,然后让你任选其中一个给出解(构造出满足条件的方案)。这些问题可能是:
- 求满足 ... 条件的简单路径。
- 求满足 ... 条件的简单环。
- 求满足 ... 条件的子图(独立集,团,...)。
- 求满足 ... 条件的边集。
- ......
比较基础的方法是:对其中一个任务,看出它所需的充分必要条件 (X)。判断一下所给的图,如果满足 (X),则直接输出答案。否则问题转化为:【给出一张图,保证不满足 (X),请完成任务 2】。对着这个问题大力思考即可。如果不能一眼看出充分必要条件,那至少找一个充分条件。看看此时另一个任务是否必能完成。此外,还可以先尝试解决其中一个任务。在解决的过程中,逐渐发现性质,或者发现两个任务的内在联系。
在无向图上,DFS 树是一个非常强大的工具,我们要善用它。
如果涉及到点的度数有关的问题,可以考虑每次把度数最小的点删去,然后更新其他点的度数。