Python-匈牙利算法

部署运行你感兴趣的模型镜像

匈牙利算法(Hungarian Algorithm)是一种解决二分图最大匹配(Maximum Bipartite Matching)问题的经典算法。在一个二分图中,该算法能够找到最大的匹配,即在给定的两组顶点中找到最大数量的边,使得每个顶点都最多与一个相邻顶点相连。

我们通过一个简单的例子来说明匈牙利算法的工作过程。
假设我们有一个二分图,如下所示:

   1  2  3  4
A  3  2  0  1
B  2  4  1  0
C  1  3  2  1
D  0  2  5  2

这里,顶点分为两组:A, B, C, D是左边的未匹配顶点,1, 2, 3, 4是右边的未匹配顶点。图中的数字代表边的权重。
首先,我们进行初始化,将所有边的权重设为0,并为左边的每个顶点设定初始标号。在匈牙利算法中,左边的顶点对应于任务,右边的顶点对应于工人。初始时,我们将左边的顶点标号设为0。

1.初始化:

   1  2  3  4
A  3  2  0  1
B  2  4  1  0
C  1  3  2  1
D  0  2  5  2

初始标号:

A: 0
B: 0
C: 0
D: 0

现在,我们从A开始寻找增广路径。我们可以从每个顶点出发,依次找到能够增加匹配数的路径。

2.寻找增广路径:

从A开始,我们看到A有两条边,分别指向3和4。我们首先看3:

        A - 3,这条边没有匹配,我们可以将A与3匹配。
        接着,我们看A - 4,这条边也没有匹配,我们可以将A与4匹配。

        现在我们有两个匹配:A - 3和A - 4。

3.标记未匹配顶点:

现在,我们看B。B有边2和1,我们可以选择B - 1:

B - 1,这条边没有匹配,我们可以将B与1匹配。

现在我们有三个匹配:A - 3,A - 4,B - 1。
接着我们看C:

C - 3,这条边没有匹配,我们可以将C与3匹配。

现在我们有四个匹配:A - 3,A - 4,B - 1,C - 3。
最后我们看D:

D - 2,这条边没有匹配,我们可以将D与2匹配。

现在我们有五个匹配:A - 3,A - 4,B - 1,C - 3,D - 2。
现在,每个任务都已经分配给了一个工人,我们找到了一个最大匹配。

4.结果:

最终的最大匹配为:

A - 3
B - 1
C - 3
D - 2

这就是匈牙利算法的基本工作原理。在实际应用中,算法会根据实际情况不断更新顶点的标号,并寻找增广路径,直到无法再找到增广路径为止,从而得到最大的匹配。

算法步骤总结

  1. 初始化:将所有的边的权重设为0,并找到所有顶点的初始标号(后文详述)。
  2. 寻找增广路径:从左边的每个未匹配顶点开始,尝试通过增广路径的方式寻找增加匹配数的可能性。
  3. 标记未匹配顶点:如果找到增广路径,就将路径上的顶点标记为已匹配,并尝试为其他未匹配的顶点寻找增广路径。
  4. 更新标号:如果无法找到增广路径,则根据标号更新算法重新调整顶点的权重,以便寻找更多的增广路径。
  5. 重复步骤2-4,直到无法再找到增广路径为止。

代码实现:

class HungarianAlgorithm:
    def __init__(self, graph):
        self.graph = graph
        self.rows = len(graph)
        self.cols = len(graph[0])
        self.matched = [-1] * self.cols  # 存储匹配情况,初始化为-1
        self.visited = [False] * self.cols  # 用于DFS的访问标记

    def find_matching(self):
        match_count = 0  # 匹配数量

        # 尝试为每个未匹配的左侧顶点寻找匹配
        for i in range(self.rows):
            self.visited = [False] * self.cols
            if self.dfs(i):
                match_count += 1

        return match_count, self.matched

    def dfs(self, u):
        # 尝试匹配顶点u
        for v in range(self.cols):
            if self.graph[u][v] and not self.visited[v]:
                self.visited[v] = True

                # 如果顶点v未被匹配或者v的匹配顶点能够找到增广路径
                if self.matched[v] == -1 or self.dfs(self.matched[v]):
                    self.matched[v] = u
                    return True

        return False

# 示例用法
if __name__ == "__main__":
    # 定义二分图的邻接矩阵表示
    graph = [
        [0, 1, 1, 0],
        [1, 0, 0, 1],
        [0, 0, 1, 0],
        [0, 0, 1, 1]
    ]

    # 创建匈牙利算法对象并执行匈牙利算法
    hungarian = HungarianAlgorithm(graph)
    max_matching, matching_result = hungarian.find_matching()

    # 打印匹配结果
    print("最大匹配数量:", max_matching)
    print("匹配结果:", matching_result)

您可能感兴趣的与本文相关的镜像

Langchain-Chatchat

Langchain-Chatchat

AI应用
Langchain

Langchain-Chatchat 是一个基于 ChatGLM 等大语言模型和 Langchain 应用框架实现的开源项目,旨在构建一个可以离线部署的本地知识库问答系统。它通过检索增强生成 (RAG) 的方法,让用户能够以自然语言与本地文件、数据库或搜索引擎进行交互,并支持多种大模型和向量数据库的集成,以及提供 WebUI 和 API 服务

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值