匈牙利算法

匈牙利算法

定理一

设指派问题的效率矩阵为C=(cij)n×n,若将该矩阵的某一行或列的个元素都减去同一个常数t,得到新的效率矩阵C=(cij)n×n,则以C为效率矩阵的新指派问题与原指派问题的最优解相同,但其最优解比原最优解值减少t.

证明 根据指派问题的定义
z ′ = ∑ i = 1 n ∑ j = 1 n c i j ′ x i j z^{'}= \sum_{i=1}^n\sum_{j=1}^nc^{'}_{ij}x_{ij} z=i=1nj=1ncijxij

= ∑ i = 1 , i ≠ k n ∑ j = 1 n c i j ′ x i j + ∑ j = 1 n c k j ′ x k j =\sum_{i=1,i≠k}^n\sum_{j=1}^nc^{'}_{ij}x_{ij}+\sum_{j=1}^nc^{'}_{kj}x_{kj} =i=1,i=knj=1ncijxij+j=1nckjxkj

= ∑ i = 1 , i ≠ k n ∑ j = 1 n c i j x i j + ∑ j = 1 n ( c k j − t ) x k j =\sum_{i=1,i≠k}^n\sum_{j=1}^nc_{ij}x_{ij}+\sum_{j=1}^n(c_{kj}-t)x_{kj} =i=1,i=knj=1ncijxij+j=1n(ckjt)xkj

= ∑ i = 1 , i ≠ k n ∑ j = 1 n c i j x i j + ∑ j = 1 n c k j x k j − t ∑ j = 1 n x k j =\sum_{i=1,i≠k}^n\sum_{j=1}^nc_{ij}x_{ij}+\sum_{j=1}^nc_{kj}x_{kj}-t\sum_{j=1}^nx_{kj} =i=1,i=knj=1ncijxij+j=1nckjxkjtj=1nxkj

指派问题定义得第k个人只能在1...n项工作中选一个,所以最后一项为1 \text{指派问题定义得第k个人只能在1...n项工作中选一个,所以最后一项为1} 指派问题定义得第k个人只能在1...n项工作中选一个,所以最后一项为1

= z − t =z-t =zt

定理2

若将指派问题的效率矩阵每一行及每一列分别减去其中得最小元素,则得到的新指派问题与原指派问题有相同得最优解。

新的C中出现的元素cij=0表示第i个人去干第j项工作效率最好

独立零元素: 在效率矩阵C中,有一组处在不同行不同列的零元素,称为独立零元素组,此时其中每个元素称为独立零元素

例1:由效率矩阵得独立零元素组确定最优指派问题
C = [ 5 0 2 0 2 3 0 0 0 5 6 7 4 8 0 0 ] C=\begin{bmatrix} 5 & 0 & 2 & 0\\ 2 & 3 & 0 & 0 \\ 0 & 5 & 6 & 7 \\ 4 & 8 & 0& 0 \end{bmatrix} C=5204035820600070

$
X_{(1)}=\begin{bmatrix}
0 & 1 & 0 & 0\
0 & 0 & 0 & 1 \
1 & 0 & 0 & 0 \
0 & 0 & 1& 0
\end{bmatrix}
$

但有的问题中发现效率矩阵C独立零元素的个数不到n个,这样就无法求到最优指派方案,需要进一步的分析

定理3:效率矩阵C中独立零元素的最多个数等于能覆盖所有零元素的最少直线条数

例2:现有一个5×5的指派问题,其效率矩阵如下,求该指派问题
C = [ 12 7 9 7 9 8 9 6 6 6 7 17 12 14 9 15 14 6 6 10 4 10 7 10 9 ] C=\begin{bmatrix} 12 & 7 & 9 & 7 & 9\\ 8 & 9 & 6 & 6 & 6 \\ 7 & 17 & 12 & 14 & 9 \\ 15 & 14 & 6& 6 & 10\\ 4 & 10 &7 &10 & 9 \end{bmatrix} C=1287154791714109612677614610969109

匈牙利算法的求解步骤

① 变化效率矩阵,将各行各列都减去当前各行各列的最小元素
得到
C 1 = [ 5 0 2 0 2 2 3 0 0 0 0 10 5 7 2 9 8 0 0 4 0 6 3 6 5 ] C_{1}=\begin{bmatrix} 5 & 0 & 2 & 0 & 2\\ 2 & 3 & 0 & 0 & 0 \\ 0 & 10 & 5 & 7 & 2 \\ 9 & 8 & 0 & 0 & 4 \\ 0 & 6 & 3 & 6 & 5 \end{bmatrix} C1=52090031086205030070620245

② 用圈零法求出新矩阵C1中独立零元素

  1. 进行行检验:对C1进行逐行检查,每行只有一个未标记的零元素时,用⚪将该元素圈起,然后将被圈起的零元素所在列的其他未标记的零元素用记号×划去 重复进行行检验直到每一行都没有未被标记的零元素或至少有两个未被标记的零元素为止
  2. 进行列检验:与行检验类似
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9El4yxxv-1645065578272)(:/294c28e8718447bebd993fc8d237f6d0)]

③针对出现的3种情况进行试指派:
1每行具有圈0,个数m=n,则得到最优解
2存在未被标记的零元素,但他们所在行列中,未被标记的零元素均至少有两个,可得到最优解
3不存在违背标记过的零元素,但圈0个数m<n 进入第4步

④做最少直线覆盖当前所有零元素
在这里插入图片描述

(1)对C3中所有不含圈0元素的行打√
(2)对打√的行中所有零元素所在列打√
(3)对所有打√列中圈0元素所在行打√
(4)重复上述第(2)和(3)步,直到不能继续为止
(5)对未打√的每一行画一直线,对已打√的每一列画一纵线
在这里插入图片描述

⑤对矩阵C4做进一步交换以增加0元素
在未被直线覆盖过的元素中找出最小元素,将打√行的各元素减去这个最小元素,将打√列的个元素加上这个最小元素,(以避免出现负元素)注 这里的打√指的是第4步中的操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-otWrc30Q-1645065578275)(:/b2550ea1d7d44c688ba687e256e725cc)]

⑥对已增加独立零元素的矩阵回到第2步再进行操作,知道出现圈0的个数m=n为止
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wbl3PbIB-1645065578276)(:/56764931d66a46009435d5a5bdad7074)]

如果是最大化指派问题

m a x ∑ i = 1 n ∑ j = 1 n c i j x i j max \sum_{i=1}^n\sum_{j=1}^nc_{ij}x_{ij} maxi=1nj=1ncijxij

s . t . ∑ j = 1 n = 1 s.t. \sum_{j=1}^n=1 s.t.j=1n=1

∑ i = 1 n = 1 \sum_{i=1}^n=1 i=1n=1

x i j = 0 或 1 x_{ij}=0或1 xij=01

m a x   z = ∑ i = 1 n ∑ j = 1 n c i j x i j ⇒ m i n   ( − z ) = ∑ i = 1 n ∑ j = 1 n ( − c i j ) x i j max \: z=\sum_{i=1}^n\sum_{j=1}^nc_{ij}x_{ij}\Rightarrow min \: (-z)=\sum_{i=1}^n\sum_{j=1}^n(-c_{ij})x_{ij} maxz=i=1nj=1ncijxijmin(z)=i=1nj=1n(cij)xij

不能直接使用匈牙利算法,因为它要求每个元素都非负
进行转化 在效率矩阵中找出一个最大元素M,并令
b i j = M − c i j    i , j = 1 , 2 , . . . , n b_{ij}=M-c_{ij} \:\: i,j=1,2,...,n bij=Mciji,j=1,2,...,n
不难发现这两个问题等价
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AM1YDA2f-1645065578277)(:/4ce12762ffd64fdfb608e281a123cf35)]

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值