python 实现匈牙利算法求解二分图最大匹配

​ 重点:理解增广路和取反

1. 匈牙利算法

  • 求解目标:找到二分图的最大匹配
  • 整体思路:每一步寻找一条增广路径,取反

2. 关键步骤

二分图的顶点分为左边点集X和右边点集Y,假定遍历的点集是X。对于每一次迭代的点x_i,

  1. 搜索增广路径:遍历x_i的邻接节点y_j
    1. 如果y_j未匹配,则找到增广路
    2. 如果y_j已匹配,则寻找y_j的匹配节点的增广路径(深搜或者广搜)
  2. 取反:把增广路径中的已经匹配边改成未匹配;未匹配的改成匹配

3. python代码

​ 算法输入为字典形式的特殊邻接表。特殊之处在于字典的键和值的顶点分别属于二分图的左右点集合。

​ 深度搜索增广路径函数的参数中的visited_set的作用是避免重复访问。

# 匈牙利算法(dfs)
class Hungarian:

    def search_extend_path(self, l_node, adjoin_map, l_match, r_match, visited_set):
        '''深度搜索增广路径'''
        for r_node in adjoin_map[l_node]:  # 邻接节点
            if r_node not in r_match.keys():  # 情况1: 未匹配, 则找到增广路径,取反
                l_match[l_node] = r_node
                r_match[r_node] = l_node
                return True
            else:  # 情况2: 已匹配
                next_l_node = r_match[r_node]
                if next_l_node not in visited_set:
                    visited_set.add(next_l_node)
                    if self.search_extend_path(next_l_node, adjoin_map, l_match, r_match, visited_set):  # 找到增广路径,取反
                        l_match[l_node] = r_node
                        r_match[r_node] = l_node
                        return True
                    return False

    def run(self, adjoin_map):
        '''
        :param adjoin_map: {x_i: [y_j, y_k]}
        :return:
        '''
        l_match, r_match = {}, {}  # 存放匹配
        for lNode in adjoin_map.keys():
            self.search_extend_path(lNode, adjoin_map, l_match, r_match, set())
        return l_match

二分图匹配——匈牙利算法和KM算法

posted @ 2020-03-03 23:57  vlj  阅读(2722)  评论(0编辑  收藏  举报