最小路径覆盖:针对一个有向无环图(DAG),用最少条互不相交路径,覆盖所有点。(其中互不相交是指点不重复)
结论:最小路径点覆盖(最小路径覆盖) = 总点数 - 最大匹配
证明:
1.建图
求最小路径覆盖用到拆点,一个点分成两个点,分别表示出点和入点,
那么从点i->j的一条边就用,从左边的出点i连到右边的入点j’表示,
于是得到的图是一个二分图,因为所有的边都是在左部和右部之间的,内部没有点。
2.转化
此时将原图中的每一条路径转化到新图中,因为原图中的路径互不相交,所以每一个点最多只有一个出度和入度,
这就意味着在新图中,左部每一个点最多只会向右部连一条边,右部的点最多只会有一条边连入,每个点最多只会属于一条边。
①原图中的一条路径<=>新图中的一组匹配(新图中每一个点最多只会属于一条边)
②原图中每一条路径的终点(没有出边)<=>新图左部的非匹配点
3.推导
求原图中互不相交路径数<=>求路径终点数最少<=>求左部非匹配点最少<=>求最大匹配
拓展:
最小路径重复点覆盖:在最小路径覆盖问题的基础上,去掉互不相交。
结论:记原图G,求传递闭包后的图G’,则G的最小路径重复点覆盖=G’的最小路径覆盖
在该题中,记最小路径重复点覆盖数为cnt,该题的答案就是cnt
证明:
①k<=cnt
这cnt条路径覆盖了所有的点,所以所求的k个点一定要从这cnt条路径中的点选,
并且每条路径上最多选一个点,所以k<=cnt
②k>=cnt
构造:将cnt条路径的终点都放到一个集合E中,记next(E)返回的是从E中的每个点出发能到的所有点的集合
分类讨论:
i)E ∩ next(E) = Ø ,此时E内的点不能相互到达,说明E中所有的点就是一种k=cnt的方案
ii)E ∩ next(E) ≠ Ø , 对于E中的任何一个点p,让这个点反向走,直到这个点走到一个不在next(E-p)中的点,可证当这个点走到起点时肯定不在next(E-p)中。
反证法:如果这个点走到起点,仍在next(E-p)中,说明p所在的路径的起点可以被其他路径到达,那么这条路径就没有存在的意义可以省去,不满足最小路径重复点覆盖。
所以此时同样可以在每一条路径中选出一个点,使得这些点之间两两不可到达,即k=cnt
C++ 代码
#include <iostream>
#include <cstring>
using namespace std;
const int N = 210 , M = 30010;
bool d[N][N];
bool st[N];
int n , m;
int match[N];
bool find(int x)
{
for(int i = 1 ; i <= n ; i++)
{
if(d[x][i] && !st[i])
{
st[i] = true;
if(!match[i] || find(match[i]))
{
match[i] = x;
return true;
}
}
}
return false;
}
int main()
{
cin >> n >> m;
while(m--)
{
int a , b;
cin >> a >> b;
d[a][b] = true;
}
for(int k = 1 ; k <= n ; k++)//求传递闭包
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
d[i][j] |= d[i][k] & d[k][j];
int res = 0;
for(int i = 1 ; i <= n ; i++)
{
memset(st , 0 , sizeof st);
if(find(i)) res++;
}
cout << n - res << endl;
return 0;
}
什么时候说过原图中路径互不相交?原图只是有向无环,并无这个条件
您真聪明
感觉也没说错吧,y总在提高课里也说了,满足要求的路径再转化到新图中,选出来的边必然是没有公共点的(每个点最多只会在一条边里)
而且作者在2.转化中说原图中的路径是互不相交的,到了3.推导中,又从“求原图中互不相交的路径数”出发,如果原图的路径是互不相交的,那直接求起点数不就好了吗?
我也没搞懂大佬,DAG并不意味着路径不相交呀,我有点没搞懂y总的证明,请问您能解释一下吗
我(蒟蒻一个)也不是看的y总的证明,我在网上搜的,
证明步骤:
构造最大匹配:考虑一个路径图 G,其中顶点数目为 n。我们可以通过简单的贪心策略找到一个最大匹配 𝑀。从路径的一端开始,选择每条可能的边加入匹配中,直到无法再添加边为止。这样得到的匹配 𝑀是最大的,因为它已经包含了尽可能多的边。
构建最小路径点覆盖:一旦找到了最大匹配 𝑀,我们可以注意到匹配中的每条边都恰好覆盖了两个顶点。每条未被匹配的边(即不在 𝑀 中的边)都必须至少由一个端点来覆盖。因此,未被匹配的顶点(即没有出现在 𝑀 中的任何边上的顶点)构成了最小路径点覆盖的一个部分。另外,由于每个匹配的边都覆盖了两个顶点,我们可以将这些边上的任意一个顶点选入最小路径点覆盖集中,以确保覆盖所有边。
计算最小路径点覆盖的大小:假设最大匹配 𝑀包含了 𝑚 条边,则它覆盖了 2𝑚个顶点(每个边覆盖两个顶点)。未被匹配的顶点数量是 𝑛−2𝑚。因此,最小路径点覆盖的大小是未被匹配的顶点数量加上匹配边的数量(每个匹配边选择一个顶点),即 𝑛−2𝑚+𝑚=𝑛−𝑚。
Orz感谢大佬
好兄弟搞懂了吗,能给我再讲讲吗,看不懂大佬写的
,”每一个点最多只有一个出度和入度,“这句话不是很对,模拟一下样例就看出来了,
理解这个问题不用看这个。
有个疑问,最后相交不为空集的情况,第一次选出的点和第二次选出的点可以保证互不可达吗,第一次选出的点只能保证其它终点到不了,但不能保证第二次选出的点到不了,还有第一次选出的点是不是也可能可以到其它终点,这不是不满足互补达的条件吗
->求路径终点数最少
这句话是不对,对于图1->2->4->5 加上一条3->2的边很显然结果应该是2,但是终点数是1,所以正确应该是说max(起点数,终点数),因为有向无环图所以可以倒着看图。
有向图怎么倒着看图?又不是无向图
请问dag中的最小路径重复点覆盖,直接求入度为零的点的个数不行吗
请问这题的答案为什么是最小路径重复点覆盖问题,能通俗的解释下吗
这个证明都写在上面了,如果不好理解可以再看看y总视频
有一个小问题(也是我看lyd的做法时有疑惑的地方):
在您的反证法里,一个点走到起点依然被另外的点覆盖到,则此路径必可以被代替,但是这是开始第一个点走的情况,在此之后,next里不仅有终点的覆盖点了,还有已经走出来的点的覆盖点集。就是说,此时这个路径不一定能被完全替代,别的路径走过来可能需要在中间拐个岔子,而不是到了终点再往这条路径上走。
这个时候怎么说明点一定存在有一个合适的位置?
这题时间太长了,有点忘了,您可以去y总的视频下面问问。
我斗胆唱反调另外发了一篇题解,不知道有没有问题
这有啥呀😂,得要有自己的想法。
next(E)是终点可以到的集合,E是终点,倒退的是E里面的点,next(E)里面的点没有变化,所以如果退到起点还在next(E)里面的话,就可以说明这个路径没必要存在
从代码来看,$\text{next}(E)$是会变化的,所以蓝书(第六版)上面的都写错了,应该是重复步骤$2$ ~ $4$,而不是$3$ ~ $4$