二分图的匹配的知识点需要掌握以下几个概念:
1.匹配点、非匹配点、匹配边、非匹配边
2.匹配、最大匹配
3.增广路
求二分图的最大匹配算法:匈牙利算法
其本质就是通过枚举每一个点,尝试找出一条增广路。而每次寻找成功后,必然会使得匹配边数量增加1:可形象地理解为:一个单身狗抢了一个别人的妹子,但是这个人他有备胎,他和备胎又成了一对,而备胎的男友又有备胎,以此类推,最终会使得情侣对数加上1。代码如下:
bool find(int x){
for(int i=head[x];i;i=ne[i]){
int j=to[i];
if(!st[j]){
st[j]=true;
if(!match[j] || find(match[j])){
match[j]=x;
return true;
}
}
}
return false;
}
//主函数部分
int res=0;
for(int i=1;i<=n1;i++){
//枚举二分图的一边
memset(st,false,sizeof st);//每次寻找增广路都要清空判重数组
if(find(i)) res++;
}
cout<<res<<endl;
把问题转化为二分图匹配问题要关注到题中的两个要素:
0要素:分成的两部分之间没有边相连
1要素:两个点之间仅存在之多一条匹配边
例题1:AcWing 372.棋盘覆盖
这个题目还是巧妙地把问题变成了图论问题,根据题意,我们不妨把骨牌的一半染成白色,另一半染成黑色,而这样整个棋盘就变成黑白相间的了。也就是说任意一个格点的上下左右格点的颜色都与其不同,这与二分图的性质极其相似,那么我们就可以在相邻的两个格点间连边,放一个骨牌就相当于选中了一条边,这样这个问题就完美转化为了二分图的最大匹配问题。代码有些小细节要注意:
#include<iostream>
#include<cstring>
#define x first
#define y second
using namespace std;
const int N=105,M=2*N*N;
int n,m;
bool ban[N][N],st[N][N];
typedef pair<int,i