这个算法理解起来比较的困难,而且网上很多博客讲的不够具体,甚至有些是错误的。这次我将用一个例子来演示这个算法的流程,帮助理解。
不涉及证明:它的算法思路和匈牙利算法相似,只不过多出来了一个处理奇环的操作。
题目
题解
一般图的最大匹配裸题
一般图最大匹配的算法流程
思路流程引用自带花树算法初学
规定三类点:
- id[i] = -1 :表示节点i从未访问过
- id[i] = 0 :表示这个点是可拓展点(S点,不妨理解为start,相当于新的寻找点)
- id[i] = 1: 表示这个点是待寻找新的匹配点的点(T点,不妨理解为terminal点)
举例说明:一个图是 1—2—3,(2,3)之前匹配好了,现在轮到1节点去找增广路,id[1] = 0。遇到2号节点是匹配好的,id[2] = 1, id[3] = 0.相当于将1转移到了3节点,再从3号节点去寻找增广路径。
流程:
从未匹配过的点x出发寻找增广路,假设找到了y,并且id[y] = -1,有下面的两种情况:
①y没有匹配边,那么结束算法,(x, y)匹配成功。
②y有匹配边,那么使id[y] = 1, 假设y的匹配节点为z,使id[z] = 0。id[y] = 0.此时说明遇到了奇环。且x, y在这个环中距离他们的lca是最远的。我们试图将(x, y)之间连一条匹配边,如果环中有一个点可以连接外面的点。
id[y] = 1.跳过对这个点的探索。
奇环的例子
样例:
6 6
1 5 1 2 2 3 3 4 4 6 4 5
因为是用链式前向星来存图的,所以图的顺序是逆过来的。
初始状态:
一开始的匹配:
待匹配的5号节点,以及入队的点:
3号点的探索:
3号节点探测出来奇环:
寻找lca,以及维护的信息,环中的id[] == 1的点入队(此处多了之前维护的pre[]的示例):
最终增广的结果,注意pre[]记录以及match[]两个数组记录了需要增广的边。两者交替进行:
看完了上面的流程图,是不是有了新的理解呢?
偶环的例子
为什么遇到了偶环和二分图的最大匹配是一样的呢?因为它只要找到了增广路就会增广,不会出现奇环那样:即使里面的n-1(n为奇)个点已经匹配好了,但是依旧会增广。偶环里面的n个点最少会有n-1个节点匹配,(还有一个节点若依旧找到了增广路依旧会增广。)
偶环中的一个点被孤立的样子:
下面是具体的例子:
<一>初始状态,外点连接匹配点:
情况①:外面的点和已匹配点寻找增广:
情况②:环内的两点可增广:
<二>初始状态,外点连接未匹配点:
情况①:外点和环内的点直接可增广
情况②: 偶环内的连点直接匹配:
更多的例子,都可以构造,发现和二分图的最大匹配流程都是一样的:
AC代码
复杂度:O(\(n^3\))
|
|
自己的一些理解
- 不论是奇环还是偶环,环里面的点都能组成很大(不是最大)的匹配。
- 若是奇环,最少也能组成\(\frac{n-1}{2}\)组匹配。现在我们要设计一种算法,看看剩下的那个点是否也能够利用。若奇环中的一个点能够和外面的路构成新的匹配,那么剩下的n-1一个节点就能两两匹配了,十分充分的利用了所有的点。
- 若是偶环,至少n-1(n为偶数)参与匹配。即使剩余了一个点。剩余的那个点和旁边的点其实也可以匹配,只不过由于匹配的顺序,而被环外的点抢占了。因此,偶环无论怎样,它的所有点都是被充分的利用的。无需设计新的算法来求解。
参考的博客
未解决的问题
赶快去刷题,总结自己的模板。
刷题推荐