询问最大二分匹配算法的时间复杂度(含经典问题及实现链接)
最大二分匹配:问题场景、实现与时间复杂度解析
嘿,咱们来好好拆解这个经典的二分匹配问题、它的解法,还有你问到的时间复杂度问题~
问题场景回顾
这是个非常典型的二分图匹配场景:
- 有M名求职者和N个岗位两个不相交的集合
- 每位求职者只对部分岗位感兴趣(可以理解为二分图里的边)
- 约束条件:每个岗位仅能接收1名求职者,每名求职者也只能被分配1个岗位
- 目标:找到能让尽可能多求职者获得工作的分配方案
这本质上就是求二分图的最大匹配——也就是找到最多的边数,保证每个节点只出现在一条边里。
基于DFS的增广路径算法实现
解决这个问题最常用的是基于深度优先搜索(DFS)的增广路径查找算法,核心逻辑是:不断为未匹配的求职者寻找可匹配的岗位,如果目标岗位已经被其他求职者占据,就尝试给那个已匹配的求职者重新找一个岗位(也就是寻找增广路径),直到找不到更多有效匹配为止。
下面是一段可运行的Python实现代码:
def max_bipartite_matching(graph, num_applicants, num_jobs): # match_to[j] 记录岗位j当前匹配的求职者编号 match_to = [-1] * num_jobs total_matches = 0 def dfs(applicant, visited_jobs): # 遍历当前求职者感兴趣的所有岗位 for job in range(num_jobs): if graph[applicant][job] and not visited_jobs[job]: visited_jobs[job] = True # 如果岗位未被匹配,或者已匹配的求职者能找到新岗位 if match_to[job] == -1 or dfs(match_to[job], visited_jobs): match_to[job] = applicant return True return False # 逐个处理每个求职者 for applicant in range(num_applicants): visited = [False] * num_jobs if dfs(applicant, visited): total_matches += 1 return total_matches # 示例测试:graph[i][j] = 1 表示求职者i对岗位j感兴趣 sample_graph = [ [1, 1, 0], [1, 0, 1], [0, 1, 0] ] print(max_bipartite_matching(sample_graph, 3, 3)) # 输出3,实现全员匹配
时间复杂度说明
基于DFS的基础算法
这个算法的时间复杂度是 O(V×E):
- V代表左集合的节点数量(这里就是求职者的数量M)
- E代表二分图中边的总数量(所有求职者感兴趣的岗位总数)
拆解一下计算逻辑:
- 我们需要为每个求职者最多执行一次DFS,总共V次DFS调用
- 每次DFS过程中,最多会遍历所有的边(E条)
- 两者相乘就得到了O(V×E)的时间复杂度
更高效的进阶算法
如果处理大规模的二分图匹配场景(比如上万级别的节点),可以使用Hopcroft-Karp算法,它的时间复杂度能优化到 O(E×√V),通过批量寻找增广路径来减少重复计算,效率会比基础DFS版本高很多。
内容的提问来源于stack exchange,提问作者Shalini Tomar




