匈牙利算法,KM算法Python实现

匈牙利算法

# -*- coding: utf-8 -*-
"""
匈牙利算法
O(E*V)
"""
def Hungarian(l_node, visited):
    for r_node in graph[l_node]:
        if r_node not in T:
            S[l_node] = r_node
            T[r_node] = l_node
            return True
        else:
            l_next_node = T[r_node]
            if l_next_node not in visited:
                visited.add(l_next_node)
                if Hungarian(l_next_node, visited):
                    S[l_node] = r_node
                    T[r_node] = l_node
                    return True
    return False

graph = {1: [1, 2, 3],
         2: [1, 2, 4, 5],
         3: [2, 3],
         4: [2, 3],
         5: [4, 5]}
S, T = {}, {}
for lNode in graph.keys():
    Hungarian(lNode, set())
    print(S)

KM算法

"""
KM算法
复杂度O(E*V*V)?
"""
a = -float('inf')
# a = 5
graph = [
    [4, 2, 6, a, a],
    [2, 6, a, 6, 3],
    [a, 3, 6, a, a],
    [a, 8, 2, a, a],
    [a, a, a, 3, 1]
]
label_left, label_right = [max(g) for g in graph], [0 for _ in graph]
S, T = {}, {}

visited_left = [False for _ in graph]
visited_right = [False for _ in graph]
slack_right = [float('inf') for _ in graph]


def find_path(i, visited_left, visited_right, slack_right):
    visited_left[i] = True
    for j, match_weight in enumerate(graph[i]):
        if visited_right[j]:
            continue
        gap = label_left[i] + label_right[j] - match_weight
        if gap == 0:
            visited_right[j] = True
            if j not in T or find_path(T[j], visited_left, visited_right, slack_right):
                T[j] = i
                S[i] = j
                return True

        else:
            slack_right[j] = min(slack_right[j], gap)
    return False

def KM():
    m = len(graph)
    for i in range(m):
        # 重置辅助变量
        slack_right = [float('inf') for _ in range(m)]
        while True:
            visited_left = [False for _ in graph]
            visited_right = [False for _ in graph]
            if find_path(i,visited_left,visited_right, slack_right):
                break
            d = float('inf')
            for j, slack in enumerate(slack_right):
                if not visited_right[j] and slack < d:
                    d = slack
            for k in range(m):
                if visited_left[k]:
                    label_left[k] -= d
                if visited_right[k]:
                    label_right[k] += d
    return S, T

KM()
print(S)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值