最大二分图匹配算法详解

步骤1 – 翻译:将以下关于"Maximum Bipartite Matching – GeeksforGeeks"的英文技术文章翻译成中文。

二分图中,匹配是指这样一组边,其中任意两条边都没有公共端点。最大匹配是指具有最大尺寸(即边数最多)的匹配。在最大匹配中,如果再添加任何一条边,它就不再是匹配了。对于给定的二分图,可能存在不止一种最大匹配方案。

为什么我们要关注它?

许多现实世界的问题都可以转化为二分图匹配问题。例如,考虑下面这个问题:

有 M 名求职者和 N 份工作。每名求职者都有自己感兴趣的工作子集。每个职位空缺只能接受一名求职者,而一名求职者也只能被任命担任一份工作。请找到一种工作分配方案,使得尽可能多的求职者获得工作。

!<a href="https://media.geeksforgeeks.org/wp-content/cdn-uploads/maximummatching1.png">maximummatching1

我们强烈建议您先阅读以下文章:“最大流问题的 Ford-Fulkerson 算法

最大二分图匹配与最大流问题

最大二分图匹配 (MBP) 问题可以通过将其转化为流网络来解决(请观看此视频以了解我们是如何得出这一结论的)。具体步骤如下。

!<a href="https://media.geeksforgeeks.org/wp-content/cdn-uploads/maximummatching2.png">maximummatching2

1) 构建流网络:流网络必须有一个源和一个汇。因此,我们添加一个源,并添加从源到所有求职者的边。同样,添加从所有工作到汇的边。每条边的容量被标记为 1 个单位。

!<a href="https://media.geeksforgeeks.org/wp-content/cdn-uploads/maximummatching21.png">maximummatching2

2) 寻找最大流:我们使用 Ford-Fulkerson 算法在步骤 1 中构建的流网络中寻找最大流。最大流实际上就是我们寻找的 MBP。
如何实现上述方法?

让我们首先定义输入和输出形式。输入采用 Edmonds 矩阵的形式,它是一个二维数组 ‘bpGraph[M][N]‘,包含 M 行(代表 M 名求职者)和 N 列(代表 N 份工作)。如果第 i 名求职者对第 j 份工作感兴趣,则 bpGraph[i][j] 的值为 1,否则为 0。

输出是能够获得工作的最大人数。

实现这一点的一种简单方法是创建一个矩阵,表示具有 M+N+2 个顶点的有向图的邻接矩阵表示法。对该矩阵调用 fordFulkerson()。这种实现需要 O((M+N)*(M+N)) 的额外空间。

利用图是二分图且每条边的容量要么是 0 要么是 1 这一事实,可以减少额外空间并简化代码。其核心思想是使用 DFS 遍历为求职者寻找工作(类似于 Ford-Fulkerson 中的增广路径)。我们对每一名求职者调用 bpm(),bpm() 是基于 DFS 的函数,它会尝试所有可能性的分配工作给该求职者。

在 bpm() 中,我们会逐一尝试求职者 ‘u‘ 感兴趣的每一份工作,直到找到一份工作,或者尝试了所有工作但运气不佳。对于我们尝试的每一份工作,我们执行以下操作。

如果一份工作没有分配给任何人,我们 simply 将其分配给该求职者并返回 true。如果一份工作已经分配给了其他人,比如说 x,那么我们会递归地检查 x 是否可以分配其他工作。为了确保 x 不会再次获得相同的工作,我们在对 x 进行递归调用之前将工作 ‘v‘ 标记为“已见”(seen)。如果 x 可以获得其他工作,我们就更改工作 ‘v‘ 的求职者并返回 true。我们使用一个数组 maxR[0..N-1] 来存储分配给不同工作的求职者。

如果 bmp() 返回 true,这意味着流网络中存在一条增广路径,并且在 maxBPM() 的结果中添加了 1 个单位的流量。

推荐练习最大二分图匹配立即尝试!

实现:
在练习场尝试它<img src="https://www.geeksforgeeks.org/problems/maximum-bipartite-matching–170646/1" alt="redirect icon" />

C++


// A C++ program to find maximal

// Bipartite matching.

#include

#include

using namespace std;

// M is number of applicants

// and N is number of jobs

#define M 6

#define N 6

// A DFS based recursive function

// that returns true if a matching

// for vertex u is possible

bool bpm(bool bpGraph[M][N], int u,

bool seen[], int matchR[])

{

// Try every job one by one

for (int v = 0; v < N; v++)

{

// If appli

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/22077.html
点赞
0.00 平均评分 (0% 分数) - 0