【学习笔记】一类图上二选一构造问题
一类图上二选一构造问题
CF1198C Matching vs Independent Set
题目大意:
给定一张 \(3\cdot n\) 个节点、\(m\) 条边,无自环、无重边的无向连通图。
定义一个匹配是一个边的集合,满足其中任意两条边没有公共端点。
定义一个独立集是一个点的集合,满足其中任意两个点没有边直接相连。
请你找出一个 \(n\) 条边的匹配,或一个 \(n\) 个点的独立集。
数据范围:\(1\leq n\leq 10^5\),\(0\leq m\leq 5\cdot 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\)。
你需要解决以下两个问题的任何一个:
- 找出一个大小为 \(\lceil\frac{k}{2}\rceil\) 的独立集。
- 找出一个大小不超过 \(k\) 的简单环。
独立集是一个点的集合,满足其中任意两点之间在原图上没有边直接相连。
可以证明这两个问题必然有一个可以被解决。
数据范围:\(3\leq k\leq n\leq10^5\),\(n - 1\leq m\leq 2\cdot 10^5\)(边数)。
以任意点为根,建出 DFS 树。如果我们将每条边按照第一次经过时的方向进行定向,则无向图的 DFS 树满足所有非树边都是后向边(即从一个节点连向其祖先的边)。
如果存在一条非树边 \((u, v)\)(\(v\) 是 \(u\) 的祖先),满足 \(\mathrm{dep}(u) - \mathrm{dep}(v) < k\),则取 \((u, v)\) 加上 \(v\) 到 \(u\) 的树上路径即为一个长度不超过 \(k\) 的简单环。
否则我们直接将节点按照深度的奇偶性划分为两个集合。在其中较大的一个集合里,把节点按 DFS 时访问的顺序排列,取任意连续的 \(\lceil\frac{k}{2}\rceil\) 个点,就是一个大小为 \(\lceil\frac{k}{2}\rceil\) 的独立集,证明如下:
- 首先根据鸽巢原理,这个“较大的集合”,大小一定大于等于 \(\lceil\frac{k}{2}\rceil\)。
- 下面证明它是独立集:
- 因为任意一条树边的两个端点,深度的奇偶性一定不同。所以上述做法得到的集合里,不存在两个点被树边相连。
- 对于一条非树边的两个端点 \((u, v)\)(\(v\) 是 \(u\) 的祖先),设 \(d = \mathrm{dep}(u) - \mathrm{dep}(v)\),那么必有:\(d\geq k\)。把节点按 DFS 顺序排列后,\(u, v\) 之间至少有 \(d + 1\) 个点。如果想要同时取到 \(u, v\),就必须取至少 \(\lceil\frac{d + 1}{2}\rceil\) 个点。而我们只取了 \(\lceil\frac{k}{2}\rceil\) 个点。\(k\) 为奇数且 \(d = k\) 时,\(u, v\) 深度奇偶性不同,不会被同时取到;否则 \(k\) 为偶数或 \(d > k\),那么必有 \(\lceil\frac{d + 1}{2}\rceil > \lceil\frac{k}{2}\rceil\)。综上,\(u, v\) 不会被同时取到。
时间复杂度 \(\mathcal{O}(n + m)\)。
CF1325F Ehab's Last Theorem
题目大意:
给出一张 \(n\) 个点的无向连通图。
你需要解决以下两个问题的任何一个:
- 找出一个大小为 \(\lceil\sqrt{n}\rceil\) 的独立集。
- 找出一个大小至少为 \(\lceil\sqrt{n}\rceil\) 的简单环。
独立集是一个点的集合,满足其中任意两点之间在原图上没有边直接相连。
可以证明这两个问题必然有一个可以被解决。
数据范围:\(5\leq n\leq10^5\),\(n - 1\leq m\leq 2\cdot 10^5\)(边数)。
设 \(S = \lceil\sqrt{n}\rceil\)。显然 \(S \geq 3\)。
以任意点为根,建出 DFS 树。如果我们将每条边按照第一次经过时的方向进行定向,则无向图的 DFS 树满足所有非树边都是后向边(即从一个节点连向其祖先的边)。
如果存在一条非树边 \((u, v)\)(\(v\) 是 \(u\) 的祖先),满足 \(\mathrm{dep}(u) - \mathrm{dep}(v) \geq S - 1\),则取 \((u, v)\) 加上 \(v\) 到 \(u\) 的树上路径即为一个大小至少为 \(S\) 的简单环,可以完成任务 2。
否则,将节点按照深度 \(\bmod (S - 1)\) 的值,划分为 \(S - 1\) 类。此时,同一类节点如果是祖先 - 后代关系,那么它们在树上深度差至少为 \(S - 1\),因此同一类节点之间一定没有边相连。
根据鸽巢原理,至少有一类节点的数量 \(\geq \lceil\frac{n}{S - 1}\rceil\geq S\),于是我们就找到了一个大小至少为 \(S\) 的独立集,任取其中 \(S\) 个节点,即可完成任务 1。
时间复杂度 \(\mathcal{O}(n + m)\)。
CF1391E Pairs of Pairs
题目大意:
给定一张 \(n\) 个节点、\(m\) 条边,无自环、无重边的无向连通图。
考虑将其中的一些节点配对,使得每个节点至多只出现在一对中。如果对于任意两对节点,这 \(4\) 个点的生成子图至多只有 \(2\) 条边,则称该配对方案是合法的。
你需要解决以下两个问题的任何一个:
- 找出一条包含至少 \(\lceil\frac{n}{2}\rceil\) 个节点的简单路径。
- 找出一组包含至少 \(\lceil\frac{n}{2}\rceil\) 个节点的合法的配对方案。
可以证明这两个问题必然有一个可以被解决。
数据范围:\(2\leq n\leq 5\cdot 10^5\),\(1\leq m\leq 10^6\)。
设 \(l = \lceil\frac{n}{2}\rceil\)。
以任意点为根,建出 DFS 树。
定义一个节点的深度为,它到根路径上的点数。
设深度最大的点深度为 \(d\)。若 \(d \geq l\),则直接取深度最大的点到根的路径,即可完成任务 1。
否则将节点按照深度分为 \(d\) 类。对于同一类点(也就是树上同一层里的点),记它们为 \(\{u_1, u_2, \dots, u_k\}\),则依次配对:\((u_1, u_2), (u_3, u_4), \dots\)。若本层里的点数 \(k\) 为偶数,则恰好配完,否则会浪费一个。因为层数 \(d\leq l - 1\),所以最多只会浪费 \(l - 1\) 个,也就是用到的节点数量 \(\geq n - (l - 1)\geq l\)。
又因为无向图的 DFS 树上不存在横叉边,所以对于任意两对节点,这 \(4\) 个点的生成子图至多只有 \(2\) 条边。符合任务 2 的要求。
CF1439B Graph Subset Problem
题目大意:
给定一张 \(n\) 个点 \(m\) 条边的无自环、无重边无向图,以及一个正整数 \(k\)。
你需要解决以下两个问题的任何一个:
- 找出一个大小为 \(k\) 的团。也就是找出 \(k\) 个节点使得它们的生成子图是完全图。
- 找出一个子图,满足子图中任意节点都与至少 \(k\) 个同样在子图里的节点相连。
或者告知无解。
数据范围:\(1\leq n, m, k\leq 10^5\),\(k\leq n\)。
开始时,把所有点丢到一个 \(\texttt{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}(m\sqrt{m})\)。
总时间复杂度 \(\mathcal{O}(n\log n + m\sqrt{m})\)。
LOJ3113 「SDOI2019」热闹的聚会与尴尬的聚会
题目大意:
给定一张 \(n\) 个点 \(m\) 条边的简单无向图。请求出:
- 一个点集 \(A\)。设它的导出子图里,度数最小的点的度数为 \(p\)。
- 一个点集 \(B\),满足它是原图的一个独立集。设它的大小为 \(q\)。
点集 \(A\) 和 \(B\) 可以有交,也可以有节点不在任何一个点集里。
你需要构造出这样的两个点集,使得 \(\lfloor\frac{n}{p + 1}\rfloor \leq q\) 且 \(\lfloor\frac{n}{q + 1}\rfloor \leq p\)。
数据范围:\(T\leq 32\) 组测试数据。对于每组测试数据:\(1\leq n\leq 10^4\),\(1\leq m\leq 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\) 。所以独立集里的点数 \(q\geq \lceil\frac{n}{p + 1}\rceil\),所以 \((p + 1)(q + 1) > n\)。
综上,我们构造出了符合所有要求的答案。
每次取度数最小的点,并支持修改一个点的度数,可以用线段树或 \(\texttt{set}\) 实现。时间复杂度 \(\mathcal{O}((n + m)\log n)\)。
总结
在图上,题目问了你两个看似无关的问题,然后让你任选其中一个给出解(构造出满足条件的方案)。这些问题可能是:
- 求满足 ... 条件的简单路径。
- 求满足 ... 条件的简单环。
- 求满足 ... 条件的子图(独立集,团,...)。
- 求满足 ... 条件的边集。
- ......
比较基础的方法是:对其中一个任务,看出它所需的充分必要条件 \(X\)。判断一下所给的图,如果满足 \(X\),则直接输出答案。否则问题转化为:【给出一张图,保证不满足 \(X\),请完成任务 2】。对着这个问题大力思考即可。如果不能一眼看出充分必要条件,那至少找一个充分条件。看看此时另一个任务是否必能完成。此外,还可以先尝试解决其中一个任务。在解决的过程中,逐渐发现性质,或者发现两个任务的内在联系。
在无向图上,DFS 树是一个非常强大的工具,我们要善用它。
如果涉及到点的度数有关的问题,可以考虑每次把度数最小的点删去,然后更新其他点的度数。