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算法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM