二分图匹配算法是一种用于解决二分图最大匹配问题的算法。
二分图:
在圖論中,二部圖(bipartite graph)是一類特殊的圖,又稱為、偶图、雙分圖。二分圖的頂點可以分成兩個互斥的独立集 U 和 V 的圖,使得所有邊都是連結一個 U 中的點和一個 V 中的點。頂點集 U、V 被稱為是圖的兩個部分。等價的,二分圖可以被定義成圖中所有的環都有偶數個頂點
匹配 :
匹配是指将一个二分图中的左部顶点和右部顶点之间进行连线的一种关系。具体来说,匹配可以表示为二维数组 match
,其中 match[i]
表示左部第 i 个顶点匹配到了右部的哪个顶点。如果 match[i]
为 -1,则表示左部第 i 个顶点没有匹配。
最大匹配 :
对于一个二分图可能有多种匹配,如果二分图里的某一个匹配包含的边的数量,在该二分图的所有匹配中最大,那么这个匹配称为 最大匹配
二分图匹配问题就是在给定的二分图中,找到最多的一对对顶点进行匹配,使得尽可能每个顶点都有一个匹配。
以下是一个例子:
假设有一个二分图,分为左部和右部
复制代码
左部: A B C D | |
右部: X Y Z |
我们可以用一个二维数组 match
来表示匹配情况,其中 match[i]
表示左部第 i 个顶点匹配到了右部的哪个顶点。初始时,数组全部为 -1,表示还没有匹配。
那么,如何使用二分图匹配算法来解决这个问题呢?
贪心二分图匹配算法
输入:
- score: 一个 n×n 的分数矩阵,表示左部和右部每对顶点之间的匹配分数
- n: 左部或右部的顶点数
输出:
- match: 一个长度为 n 的匹配数组,表示左部和右部每个顶点之间的匹配关系
import numpy as npdef GreedyBipartiteMatching(score, n):match = np.zeros(n, dtype=int)# 遍历每一列,贪心地选择当前未匹配的分数最大的行for col in range(n):max_row = -1max_score = -float('inf')for row in range(n):if match[row] == 0 and score[row, col] > max_score:max_row = rowmax_score = score[row, col]if max_row >= 0:match[max_row] = colreturn match
主要思路是:
- 遍历每一列,也就是右部的每个顶点
- 在未匹配的左部顶点中,找到与当前右部顶点的匹配分数最大者
- 将这一对作为匹配结果
这样我们仍然可以在O(n^2)时间内求解,而不需要提前排序。
这个实现更简洁直观,去掉了排序的步骤。同时时间复杂度也保持不变。