二分图最大匹配简要整理
部分内容引自xht37的博客
图的匹配
对于无向图$G=(V,E),M\subseteq L$,若$M$中任意两条边没有公共点,则称该边集$M$为图$G$的一个匹配
定义匹配的大小为边的数量$|M|$,其中边数最大的$M$为最大匹配
无法再增加匹配边的匹配为极大匹配
显然极大匹配不一定是最大匹配,但最大匹配一定是极大匹配
匹配$M$中的边称为M-匹配边,未匹配的边称为M-未匹配边
一个点如果为$M$中匹配边的端点则称为M-匹配点(M-饱和点),否则称为M-未匹配点(M-未饱和点)
若图$G$中每个结点都是M-匹配点则称$M$为完美匹配(完全匹配)
完美匹配是最大匹配,但最大匹配不一定是完美匹配
若图中节点个数为奇数且刚好只有一点是M-未匹配点则称$M$为近完美匹配
增广路
对于匹配$M$,由匹配边和非匹配边交替构成的路径称为M-交错路
显然交错路一定为简单路
M-交错回路:满足回路和交错路条件的路径
若M-交错路的始点和终点都是M-未匹配点则称该交错路为M-增广路
性质:
1,图$G$的匹配$M$为最大匹配,当且仅当$G$中不含M-增广路
2,如果把路径上所有边的状态(是否为匹配边)取反,那么得到的新的边集 仍然是一组匹配,并且匹配的边数增加了1
二分图
二分图:节点由两个集合组成,且两个集合内部没有边的图
性质:不含奇环
完备匹配:$|M|=min\{|V1|,|V2|\},V1,V2$为二分图两点集
完备匹配是最大匹配,但最大匹配不一定是完备匹配
Hall定理
判定二分图存在完备匹配的充要条件:当且仅当任取$V1$一子集$S$,有$|N(S)>=S|$,$N(S)$表示与$S$中各结点相邻的所有节点的集合
匈牙利算法
思想:
不断寻找增广路,并把增广路上所有边的状态取反,得到一个更大的匹配,直到图中不存在增广路
过程:
依次尝试给每一个左部点$x$寻找一个匹配的右部点$y$
$y$与$x$匹配需满足下面两个条件之一:
1,$y$是非匹配点。
2,$y$已与$i$匹配,但从$i$出发能找到另一个$j$与之匹配
时间复杂度$O(nm)$
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=1010; struct edge{ int next,to; }e[maxn*maxn]; int n,m,ed,head[maxn],cnt,ans,pre[maxn]; bool vis[maxn]; void add(int x,int y) { e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt; } bool dfs(int x) { for(int v,i=head[x];i;i=e[i].next) if(!vis[v=e[i].to]) { vis[v]=1; if(!pre[v]||dfs(pre[v])) { pre[v]=x; return 1; } } return 0; } int main() { scanf("%d%d%d",&n,&m,&ed); for(int x,y,i=1;i<=ed;i++) { scanf("%d%d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d\n",ans); return 0; }
二分图多重匹配
定义:从二分图中选出尽量多的边,使任取点$v$满足$v$作为最多$a_v$条选出的边的端点,则称选出的边集为二分图的多重匹配
解法:拆点进行二分图最大匹配(将点$v$拆成$a_v$个点)
二分图最小点覆盖
图的点覆盖:对于一张无向图$(V,E)$,若存在一个点集$V'$,满足$V'⊆V$,且对于任意$e∈E$,$e$至少有一个端点属于$V'$,则称$V'$为这张无向图的一组点覆盖
二分图最小点覆盖:在二分图中,包含点数最少的一组点覆盖被称为二分图的最小点覆盖
定理:二分图最小点覆盖包含的点数,等于最大匹配包含的边数
二分图最大独立集
图的独立集:对于一张无向图$(V,E)$,若存在一个点集$V'$,满足$V'⊆V$,且对于任意$p,q∈V'$,$(p,q)∉E$,则称$V'$为这张无向图的一组独立集,包含点数最多的独立集被称为图的最大独立集
定理:二分图最大独立集包含的点数,等于$n-$最大匹配包含的边数
有向无环图的最小路径点覆盖
给定一张有向无环图,用尽量少的不相交的简单路径覆盖所有点(也就是每个点恰好被覆盖一次),这样的路径集合被称为最小路径点覆盖
拆点二分图
把每个点拆成编号为$x$和$x+n$的两个点
建立一张新的二分图,$1∼n$是左部点,$n+1∼2n$是右部点。
对原图的每条有向边$(x,y)$,在二分图的左部点$x$与右部点$y+n$之间连边
最终得到的二分图成为原图的拆点二分图
定理:有向无环图的最小路径点覆盖包含的路径条数,等于$n-$拆点二分图的最大匹配边数
证明:在最小路径点覆盖的方案中,因为所有路径不相交,所以每一个点的入度和出度都不超过1;因为每个节点都被覆盖,所以x的出度和入度至少有一个是1。因此,最小路径点覆盖中的所有边,在拆点二分图中构成一组匹配。最小路径覆盖中每条边(x,y)的起点x与二分图每条匹配边(x,y+n)的左部点x是一一对应的。特别地,对于每条路径的终点t,因为t没有出边,所以出度为0,对应在二分图中就是t匹配失败。即路径的终点和二分图左部的非匹配点是一一对应的。故而,G的最小路径点覆盖等于n减去最大匹配数。
可重复最小路径点覆盖
对原图进行传递闭包,按照普通最小路径点覆盖处理即可