匹配自学心得[day01]

本文介绍二分图的基本概念、如何判断一个图是否为二分图及二分图的最大匹配问题。详细解释了增广路定理与匈牙利算法,通过实例帮助读者理解如何求解二分图的最大匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从书和其他一些博主那里零零散散学了一些关于匹配的东西
若有错误,还望斧正

1.二分图的匹配

我们的故事从二分图开始。
有这么一句话:在图论中,匹配是指两两没有公共点的边集。二分图最大匹配问题是这样的:给出一个二分图,找一个边数最大的匹配,即选出尽量多的边,使得任意两条选中的边均没有公共点。如果,这些边把所有的点都包括进去,则称这个匹配是完美匹配。

二分图是什么呢.
----> 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 --------------这是我度娘上给出的定义

而简单一些的理解是:二分图(我们这里目前只讨论无向图,有向图的匹配问题和无向图差不多,无论是A->B,还是B->A,两者都可以匹配在一起,但具体问题具体分析),可以简单理解为此图中存在两个集合,分别称为X、Y。X中的点互相之间没有边,Y中的点互相也没有边。但X中的点和Y中的点可以有七七八八的边,将两边的点连接在了一起。

这里就会涉及到一个,二分图的判断问题。
---->可以采用涂色的方法。即我随便找一个点,涂成白色(数组中标为1),则和他有边的点涂成黑色(数组中标为2)。如此dfs下去。直到涂完最后一个点,当然在涂点的时候,还要判断是否他和已经涂上颜色的点的颜色不一样。若能清清楚楚地分成两种颜色,就说明这个图是一个二分图。

接下来判断玩二分图之后,我们就开始匹配了!

2.增广路定理+匈牙利算法

匈牙利算法的核心,就是找增广路。所以我们先来看看?增广路定理。

为了方便叙述,我们先来说几个概念。

匹配边:这条边所连接的两个点互相匹配。
未匹配边:这条边所连接的两个点不互相匹配。
未盖点:未匹配点,用于表示不与任何匹配边邻接的点,即还没有匹配上的点。而除了这些未盖点,其余都是匹配点。
交替路:从一个未盖点出发,依次经过非匹配边、匹配边、非匹配边······所得到的路径。
如若交替路的终点是一个未盖点,则称为这条交替路为一条增光路。所以增光路就是一条,起点是未盖点,终点是未盖点,且一次经过非匹配边、匹配边、非匹配边······的一条路。当然最后一条边一定是一条非匹配边。在增光路中,非匹配边比匹配边多一条!!!

增广路的作用是改进匹配。假设我们已经找到了一个匹配,如何判断这个匹配是不是最大匹配呢?
---->看增广路。如果在匹配的基础上能找到一条增广路,那只要我们把这条路上的匹配边和非匹配边相互交换,得到的匹配就会比刚才的匹配多一条边。反过来,如果我们找不到增光路,则当前的匹配就是最大匹配了。这就是增光路定理,即一个匹配是最大匹配的充分必要条件是不存在增广路(证明略,可见图论证明)。当然,这个充要条件适合于任意图,并不仅仅是二分图。

下面来说说匈牙利算法。
---->这里的匈牙利算法目前只涉及到没有权值的边(默认边的权值都为1)。
我们在写代码的时候,可以边连边找。即从一个未盖点出发,我们找一条边,如果这条边能成为一条匹配边,则直接连起来。要是这条边的另外一个点不是未盖点,没关系,我们先找其他的边,若可以成为匹配边,连起来,找下一个点。没有的话,我们就以这个点为那个起点的未盖点,然后找那个子图的增广路。

匈牙利算法(这个博主写的很易懂)。

int dfs(int x){
	for (int i=0; i<m+1; i++){//Y中m个人
		if (map[x][i] != 0 && vis[i] == 0){
			vis[i] ++;
			if (l[i] == 0 || dfs(l[i]){//l数组表示和i匹配了的那个点
				l[i] = x;
				return 1;
			}
		}	
   }

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值