声明:这是本菜在学习二分图相关知识的时候神小花儿推荐的课件中的知识。现在整理上来和大家分享。
二分图相关问题:
二分图定义及判定
二分图最大匹配
二分图最小覆盖
二分图最大独立集
二分图最小路径覆盖
二分图最优匹配
稳定婚姻问题
一、定义及判定:
定义:二分图中,顶点可以分为两个集合X和Y,每一条边的两个顶点都分别位于X和Y集合中
判定:利用BFS或者DFS进行黑白染色,共享一边的两点异色,检查是否存在矛盾
图G为二分图的充要条件是图中不含奇环
二、二分图最大匹配
定义:匹配是二分图中边的集合,且集合中的任意两条边没有公共点,包含边数最多的匹配就是最大匹配
匈牙利算法:
1、概念:交错路
对于一个匹配M,如果能找到一条奇数长度的路,使得路的第一、三、五……边不属于M,而第二、四、六……边属于M,那么这条路叫做交错路。
交错路可以“增广”,即通过适当修改得到更大的匹配。
2、定理
一个匹配为最大匹配当且仅当匹配中不存在交错路
证明相当繁琐,具体参见组合数学
可以利用BFS或者DFS实现寻找交错路
3、定理的补充
匈牙利算法的实现还依赖于一个很重要的定理:如果从一个点出发,没有找到增广路径,那么无论再从别的点出发找到多少增广路径来改变现在的匹配,从这个点出发都永远找不到增广路径。
4、复杂度
匈牙利算法只需要以每个节点为起点找一次增广路即可求得最大匹配,寻找增广路的复杂度为O(E),总的复杂度为O(VE)
{附上一段我写的朴素Hungary代码}
Program Hungary; Const maxn=10000; Var i,n,k,p,q,m,ans :Longint; pre,other,last :Array[1..maxn*2]of Longint; state :Array[1..maxn]of Boolean; res :Array[1..maxn]of Longint; Function Dfs(i:Longint):Boolean; var j,k:Longint; begin j:=last[i]; while j<>0 do begin k:=other[j]; if not state[k] then begin state[k]:=true; if (res[k]=0)or(Dfs(res[k])) then begin res[k]:=i; exit(true); end; end; j:=pre[j]; end; exit(false); end; BEGIN readln(n,m); for i:=1 to m do begin readln(p,q); inc(k);pre[k]:=last[p];last[p]:=k;other[k]:=q; end; for i:=1 to n do begin fillchar(state,sizeof(state),0); if Dfs(i) then inc(ans); end; writeln(ans); END.
5、简要说明:
简要说明:Dfs函数用于判断从k点开始是否能够找到一条交错路。对于每个可以与k匹配的顶点j,假如它未被匹配,交错路就已经找到;假如j已与某顶点x匹配,那么只需调用Dfs(x)来求证x是否可以与其它顶点匹配,如果返回true的话,仍可以使j与k匹配;这就是一次DFS。每次DFS时,要标记访问到的顶点(state[j]=true),以防死循环和重复计算。
三、二分图最小覆盖
1、定义
图的覆盖:寻找一个点集,使得图中每一条边至少有一点在该点集中
2、定理
二分图的最小覆盖=二分图的最大匹配
3、简要证明
如何构造一组最小覆盖?
求得最大匹配M后,图中已经不存在交错路。从右边未匹配的点开始,以寻找交错路的方式扩展节点,并标记路过的节点。取右边未标记的节点,左边标记的节点,则构成一组最小覆盖。
所取节点数=|M| .右边未匹配的点肯定被标记了,左边未匹配的点不可能被标记(否则找到了交错路),一条匹配边的左端点被标记,那么右端点也肯定被标记,所以所取节点恰覆盖一条匹配边。所取的点覆盖了所有边。假设存在一条边未被覆盖,则该边右端点被标记了,左端点未标记。 如果这不是一条匹配边,那么相当于找到了交错路,如果着是一条匹配边,那么右端点只能通过其匹配的左端点到达。
四、二分图最大独立集
1、定义
图的独立集:寻找一个点集,其中任意两点在图中无对应边
一般图的最大独立集是NP完全问题
2、定理
二分图的最大独立集=图的点数-最大匹配数
可以这样理解,在总的点集中,去掉最少的点,使得剩下的点相互之间没有边。用最少的点去覆盖所有的边,也就是最小覆盖。
二分图的最大独立集=图的点数-最大匹配数
五、二分图最小路径覆盖
1、定义
最小路径覆盖问题:用尽量少的不相交简单路径覆盖有向无环图的所有顶点
将每个顶点分为两个,分别在X集合和Y集合中,如果存在有向边(a,b),对应在二分图中有(Xa,Yb)
2、定理
最小路径数=节点数-最大匹配
3、简单证明
原图的路径覆盖和新图的匹配间有对应关系:
每条覆盖边都是匹配中的一条边,且只有路径的最后一个点没有被匹配上。
路径要求不能相交,恰好对应于匹配中两匹配边不能有公共端点。
于是求最大匹配后,不能被匹配上的点,即是路径的最后一个点。有多少个不能被匹配的点,就有多少条路径存在。
路径数=原点数-匹配边数。因此我们使匹配边数最大,即是使路径数最小。
六、二分图最优匹配(又称带权最大匹配)
1、定义
二分图的每条边带有权值。求一个匹配使得匹配边上的权值和最大。
一般X和Y集合顶点个数相同,最优匹配也是一个完备匹配,即每个顶点都被匹配。如果个数不相等,可以通过补点加0边实现转化。
2、基本概念:可行顶标和相等子图
可行顶标:L是一个关于结点的函数,L(x)是顶点x对应的顶标值。可行顶标对于图中的每条边(x,y)都有L(x)+L(y)>=w(x,y)
相等子图:只包含L(x)+L(y)=w(x,y)的边的子图
3、定理
如果一个相等子图中包含完备匹配,那么这个匹配就是最优匹配
证明:由于在算法过程一直保持顶标的可行性,所以任意一个匹配的权值和肯定小于等于所有结点的顶标之和,则相等子图中的完备匹配肯定是最优匹配
4、算法流程
设顶点Xi的顶标为a[i],顶点Yi的顶标为b[i]
ⅰ.初始时,a[i]为与Xi相关联的边的最大权值,b[j]=0,保证a[i]+b[j]>=w(i,j)成立
ⅱ.当相等子图中不包含完备匹配时,就适当修改顶标以扩大相等子图,直到找到完备匹配为止
ⅲ.修改顶标的方法
当从Xi寻找交错路失败后,得到一棵交错树,它的所有叶子节点都是X节点,对交错树中X顶点的顶标减少d值,Y顶点的顶标增加d值,对于图中所有的边(i,j),可以看到
i和j都不在交错树中,边(i,j)仍然不属于相等子图
i和j都在交错树中,边(i,j)仍然属于相等子图
i不在交错树中,j在交错树中,a[i]+b[j]扩大,边(i,j)不属于相等子图
5、时间复杂度
时间复杂度:需要找O(n)次增广路,每次增广最多需要修改O(n)次顶标,每次修改顶标时枚举边来求d值,复杂度为O(n2),总的复杂度为O(n4).
简单优化可以降低到O(n3),每个Y顶点一个“松弛量”函数slack,每次开始找增广路时初始化为无穷大。在寻找增广路的过程中,检查边(i,j)时,如果不在相等子图中,则让slack[j]变成原值与A[i]+B[j]-w[i,j]的较小值。这样,在修改顶标时,取所有不在交错树中的Y顶点的slack值中的最小值作为d值即可。但还要注意一点:修改顶标后,要把所有的slack值都减去d。
i在交错树,j不在交错树中,边(i,j)有可能加入到相等子图中
为了使a[i]+b[j]>=w(i,j)始终成立,且至少有一条边加入到相等子图中,d=min{a[i]+b[j]-w(i,j)},i在交错树中,j不在交错树中
七、稳定婚姻问题
完备婚姻:N位男士和N位女士,组成N对配偶,每位男士按偏爱程度对N位女士排序,每位女士对N位男士也进行排序。
如果存在两对配偶,女士A和男士a,女士B和男士b,使得A更偏爱b而非a,且b更偏爱A而非B,那么就称这个完备婚姻是不稳定的
是否总是存在稳定婚姻?
延迟认可算法
初始每位女士处于未匹配状态。
当存在未匹配女士时,该女士在所有未拒绝过她的男士中选择她最喜欢的男士作为配偶,男士在所有选择他的女士中选择他最喜欢的作为配偶
在该算法中,女士主动选择男士,女士的每次选择都会导致更不理想的配偶,而男士一但被一个他更喜欢的女士选择,则他可以“抛弃”现在的配偶。
每个女士至多选择N次,所以算法一定会终止,时间复杂度为O(N*N)
【后记:感谢神小花儿提供课件,本弱只是做了些整理工作而已,也方便自己阅读了】