详细的介绍全在《二分图最大匹配及常用建图方法》里了,我就不班门弄斧啦。
二分匹配主要求的就是最大匹配数(匈牙利算法),再通过计算得到想要的答案。
代码如下
#include<stdio.h>
#include<string.h>
const int MAXN = 1001;
int match[MAXN][MAXN]; //match数组为是否匹配,也可以用静态邻接表
int visit[MAXN]; //标记
int link[MAXN]; //link[y]表示当前与y节点相邻的x节点
int nx,ny,m; //不要定义两遍啊!
int find(int x) //是否存在X集合中节点x开始的增广路
{
int i;
for(i=1;i<=ny;i++)
{
if(!visit[i]&&match[x][i]) //如果节点i与x相邻并且未访问过
{
visit[i] = true ;
if (link[i]==-1||find(link[i])) //如果找到一个未盖点i中或从与i相邻的节点出发有增广路
{
link[i] = x;
return 1;
}
}
}
return 0;
}
int main()
{
int i;
int u,v;
memset(match,0,sizeof(match));
memset(link,-1,sizeof(link)); //当集合里有0出现时要初始化为-1;
scanf("%d%d%d",&nx,&ny,&m);
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
match[u][v]=1;
}
int sum=0;
for(i=1;i<=nx;i++)
{
memset(visit,0,sizeof(visit));
if (find(i))
sum++;
}
printf("%d\n",sum);
return 0 ;
}
例题
HDU 2063,HDU1083;
变形主要有以下三个公式:
1,最大独立集=n-最大匹配数;
例题 HDU 4619
2,最小顶点覆盖=最大匹配数;
用最少的点,让每条边都至少和一个点关联。
例题 HDU 1150
3,最小路径覆盖=n-最大匹配数;
用尽量少的不相交简单路径覆盖有向无环图(DAG)G的所有顶点,这就是DAG图的最小路径覆盖问题。例题 HDU 1151,1350(时间流,即不可能出现圈);
有些题目就是难在建图上面
例如
HDU 1507 黑白染色法,把(i+j)是否为奇偶作为黑白的判断依据;(代码)
ZOJ 1654 一行变多行,一列变多列;(代码)
算的上是实战的题目
HDU 2413 通过二分时间来求最大匹配,用上静态邻接表还要2000+MS,超时的可能性比较大。poj的时间限制会比较松。(代码)