算法笔记:匈牙利算法

1 二部图(二分图)

  • 二分图Bipartite graph)是一类特殊的,它可以被划分为两个部分,每个部分内的点互不相连。
    • 匈牙利算法主要用来解决两个问题:求二分图的最大匹配数最小点覆盖数

2 最大匹配问题

2.1 问题描述

  •  左右有两个点集,我们最多可以找到多少条没有公共端点的边?

2.2 匈牙利算法举例

  • 从B1开始,从G1~G4一个一个遍历过去
    • 首先遍历到和B1有连边的G2
    • 暂时把B1和G2连接
  • 接着看B2,也从G1~G4一个一个遍历过去

    • 首先遍历到和B2有连边的G2
    • 此时G2已经和左边的B1连接了
    • 于是倒回去看B1,看看B1有没有别的可以连接的选项
    • 发现B1在G2后还可以连接G4
    • ——>B2暂时连G2,B1暂时连G4
  • 接着看B3,首先B3会先遍历到G1
    • G没啥冲突
  • 最后看B4
    • B4遍历到G4
    • G4此时连着B1
      • B1没有别的可以连接的了
    • ——>B4没法连G4

 2.3        Python实现

2.3.1 数据和准备部分

# 左点-右点--邻接矩阵
ada_matrix=[[0,1,0,1],
           [0,1,0,0],
           [1,0,1,0],
           [0,0,0,1]]

num_left=len(ada_matrix)
num_right=len(ada_matrix[0])

right_pair=[-1]*num_right
#右点和哪个左点匹配了(一开始都是-1,表示没有匹配)

2.3.2 if_match 函数

  • 表示左点匹配到i的时候,根据right_visited的情况,左点i是否会匹配一个右点
  • right_visited表示匹配左点i的过程中,每个右点是否被考虑过
def if_match(i):
    global right_visited
    for j in range(num_right):
        if(ada_matrix[i][j]==1 and right_visited[j]==0):
            #如果右边的点和左边的点有连边;同时在考虑左点i的过程中,右点j没有被考虑过
            
            right_visited[j]=1
            
            if(right_pair[j]==-1):
                #如果左边的点现在还没有右边的点和他匹配,那么左点i和右点j连接
                right_pair[j]=i
                return True
                #左点遍历到i的时候,暂时可以匹配j(后续i点可能需要“改嫁”,但是如果只遍历到i,是不冲突的)
            elif(if_match(right_pair[j])):
                 right_pair[j]=i
                 #如果左边的点已经和别的点(right_pair[j])匹配了,那么看看(right_pair[j])能不能“改嫁”
                 #也就是看看不能选择j的情况下,(right_pair[j])能不能匹配到其他的右点
                    
                 #这是一个递归过程,进行if_match(right_pair[j])的时候,假设匹配到新的右点j'
                 #又需要判断j'是否有点和它匹配+如果匹配了,已经匹配的点能不能“改嫁”
                
                 return True
                 #左点遍历到i的时候,暂时可以匹配j(后续i点可能需要“改嫁”,但是如果只遍历到i,是不冲突的)
    return False                

2.3.3 主函数

for i in range(num_left):
    #每一个左边的点
    global right_visited
    right_visited=[0]*num_right
    #在考虑左边的点i的时候,右边的点有没有被考虑过
    print(right_pair)
    if_match(i)


'''
[-1, -1, -1, -1]
[-1, 0, -1, -1]
[-1, 1, -1, 0]
[2, 1, -1, 0]
'''

结果和前面的手动推导是一样的

3 最小点覆盖问题

  • 找到最少的一些,使二分图所有的边都至少有一个端点在这些点之中。
  • 倒过来说就是,删除包含这些点的边,可以删掉所有边
  • König定理:一个二分图中的最大匹配数等于这个图中的最小点覆盖数

参考内容:带你入门多目标跟踪(三)匈牙利算法&KM算法 - 知乎 (zhihu.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
匈牙利算法,也称为二分图最大匹配算法,是一种解决二分图最大匹配问题的经典算法。它的目标是在一个二分图中找到最大的匹配数,即找到最大的能够互相配对的节点对数。 Python是一种高级编程语言,具有简洁、易读、易学的特点,广泛应用于各个领域。在Python中,我们可以使用网络流算法库或者自己实现匈牙利算法来解决二分图最大匹配问题。 以下是匈牙利算法的基本思想和步骤: 1. 初始化一个空的匹配集合。 2. 对于每个未匹配的左侧节点,尝试将其与一个未匹配的右侧节点进行匹配。 3. 如果右侧节点未被匹配,或者已被匹配但可以通过其他路径重新匹配,那么将左侧节点与右侧节点进行匹配,并将右侧节点标记为已匹配。 4. 如果右侧节点已被匹配且无法重新匹配,那么尝试将右侧节点的当前匹配节点重新匹配到其他未匹配的左侧节点。 5. 重复步骤3和步骤4,直到无法找到更多的匹配。 在Python中,可以使用networkx库来实现匈牙利算法。以下是一个使用networkx库解决二分图最大匹配问题的示例代码: ```python import networkx as nx # 创建一个空的二分图 G = nx.Graph() # 添加左侧节点 G.add_nodes_from(['A', 'B', 'C']) # 添加右侧节点 G.add_nodes_from([1, 2, 3]) # 添加边 G.add_edges_from([('A', 1), ('A', 2), ('B', 2), ('C', 3)]) # 使用匈牙利算法求解最大匹配 matching = nx.bipartite.maximum_matching(G) # 输出最大匹配结果 print(matching) ``` 以上代码中,我们首先创建了一个空的二分图,并添加了左侧节点和右侧节点。然后,我们使用`nx.bipartite.maximum_matching`函数来求解最大匹配,并将结果存储在`matching`变量中。最后,我们输出最大匹配结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UQI-LIUWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值