二分匹配(相关知识+模板)

二分匹配的过程:

算法的核心是找增广路径的过程 --- DFS
对于每个可以与u匹配的顶点v,假如它未被匹配,可以直接用v与u匹配;
如果v已与顶点w匹配,那么只需调用dfs(w)来求证w是否可以与其它顶点匹配,如果dfs(w)返回1的话,仍可以使v与u匹配;如果dfs(w)返回0,则检查u的下一个邻接点。
在dfs时,要标记访问过的顶点(book[i] = 1),以防死循环和重复计算;每次在主过程中开始一次dfs前,所有的顶点都是未标记的。
主过程只需对每个X部的顶点调用dfs,如果返回一次1,就对最大匹配数加一;一个简单的循环就求出了最大匹配的数目。

相关定义:
1、最大匹配数:最大匹配的匹配边的数目
2、最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
3、最大独立集:选取最多的点,使任意所选两点均不相连
4、最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
5、定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)
6、定理2:最大独立集 = 顶点数 - 最小点覆盖数
7、定理3:最小路径覆盖数 = 顶点数 - 最大匹配数

二分图的最大团
1、定义:对于一般图来说,团是一个顶点集合,且由该顶点集合诱导的子图是一个完全图,简单说,就是选出一些顶点,这些顶点两两之间都有边。最大团就是使得选出的这个顶点集合最大。对于二分图来说,我们默认为左边的所有点之间都有边,右边的所有顶点之间都有边。那么,实际上,我们是要在左边找到一个顶点子集X,在右边找到一个顶点子集Y,使得X中每个顶点和Y中每个顶点之间都有边。
2、方法:二分图的最大团=补图的最大独立集。
3、补图的定义是:对于二分图中左边一点x和右边一点y,若x和y之间有边,那么在补图中没有,否则有。
4、这个方法很好理解,因为最大独立集是两两不相邻,所以最大独立集的补图两两相邻。

模板:

#include<stdio.h>
#include<string.h>
int m,n,e[110][110],match[110],book[110];
int dfs(int u)
{
	int i;
	for(i = 1; i <= n; i ++)
	{
		if(book[i] == 0 && e[u][i] == 1)
		{
			book[i] = 1;
			if(match[i] == 1 || dfs(match[i]))
			{
				match[i] = u;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	int i,x,y,sum;
	while(scanf("%d%d",&n,&m) != EOF)
	{
		sum = 0;
		memset(e,0,sizeof(e));
		memset(match,0,sizeof(match));
		for(i = 1; i <= m; i ++)
		{
			scanf("%d%d",&x,&y);
			e[x][y] = 1;
		}
		for(i = 1; i <= n; i ++)
		{
			memset(book,0,sizeof(book));
			if(dfs(i))
				sum ++;
		}
		printf("%d\n",sum);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/queen00000/article/details/81539327