匈牙利算法
匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法，并推动了后来的。美国数学家于1955年提出该算法。此算法之所以被称作匈牙利算法，是因为算法很大一部分是基于以前匈牙利数学家Dénes Kőnig和Jenő Egerváry的工作之上创建起来的。
詹姆士·芒克勒斯在1957年回顾了该算法，并发现它的时间复杂度为（强）多项式时间。 此后该算法被称为Kuhn–Munkres算法或Munkres分配算法。原始算法的时间复杂度为formula_1，但与卡普发现可以修改算法达到formula_2运行时间，富泽也独立发现了这一点。和将该方法推广到了一般运输问题。2006年发现卡爾·雅可比在19世纪就解决了指派问题，该解法在他死后在1890年以拉丁文发表。
你有三个工人：吉姆，史提夫和艾伦。 你需要其中一个清洁浴室，另一个打扫地板，第三个洗窗，但他们每个人对各项任务要求不同数目数量的钱。 以最低成本的分配工作的方式是什么？ 可以用工人做工的成本矩阵来表示该问题。例如： 当把匈牙利方法应用于上面的表格时，会给出最低成本：为6美元，让吉姆清洁浴室、史提夫打扫地板、艾伦清洗窗户就可以达到这一结果。
给定一个 formula_3 的非负矩阵，其中第 formula_4 行第 formula_5 列元素表示把第 formula_4 个工人派到第 formula_5个工作的成本。我们必须找到成本最低的工人工作分配。如果目标是找到最高成本的分配，该问题可以将每个成本都换为最高一个成本减去该成本以适应题目。
如果用二分图来阐述该问题可以更容易描述这个算法。对于一个有 formula_8个工人节点（formula_9）与 formula_8个工作节点（formula_11）的完全二分图 formula_12，每条边都有 formula_13 的非负成本。我们要找到最低成本的完美匹配。
如果函数 formula_14 满足对于每个 formula_15 都有 formula_16，则把该函数叫做势。势 formula_17 的值为 formula_18。可以看出，每个完美匹配的成本最低是每个势的值。匈牙利算法找出了完美匹配及与之成本/值相等的势，这证明了两者的最优性。实际上它找到了紧边集的完美匹配：紧边 formula_19 是指对于势 formula_17 满足 formula_21。我们将紧边子图表示为 formula_22。formula_22 中的完美匹配的成本（如果存在）就等于 formula_17的值。
在算法中我们維持 formula_22 的势formula_17和方向（表示为 formula_27 ），该方向有从 formula_11到 formula_9 的边构成匹配 formula_30 的性质。初始时，formula_17 处处为 0， 所有边都由 formula_9 指向 formula_11（因此 formula_30 为空）。每一步中，我们或者改变 formula_17 使其值增加， 或者改变方向以得到更多的边。我们保持 formula_30 的所有边都是紧边不发生改变。当 formula_30 为完美匹配时结束。
在一般的步骤中，令 formula_38 和 formula_39 为 formula_30 未覆盖的节点 （则 formula_41 包含 formula_9 中入度为零的节点，而 formula_43 中包含 formula_11 中出度为零的节点）。 令 formula_45 为从 formula_41 只沿紧边的有向路径可到达 formula_27 的节点。可由广度优先搜索求得。
若 formula_48 非空，则将 formula_27 中从 formula_41 到 formula_43 的有向路径反向。则相应匹配数增加1。
若 formula_48 为空，则令 formula_53。formula_54 为正，因为 formula_55 与 formula_56 之间没有紧边。 在 formula_57 中的节点将formula_17增加formula_54 并在 formula_55 中节点将 formula_17减小 formula_54， 得到的formula_17仍然是势。图 formula_22 改变了，但它仍包含formula_30。我们把新的边从formula_9指向formula_11。 由 formula_54 的定义，formula_41 可达的节点集 formula_70 增大（注意到紧边的数量不一定增加）。
我们重复这些步骤直到formula_30为完美匹配，该情形下给出的是最小成本（即时间消耗）的匹配。此版本的运行时间为 formula_1：formula_30 增广 formula_8次， 在 formula_30 不改变的一个阶段中，势最多改变 formula_8 次（因为 formula_70 每次都增加）。改变势所需的时间在 formula_78。
证明改变formula_79后formula_80中每条边不发生改变，这等价于证明对于formula_80中任意边，它的两个顶点要么都在formula_45中，要么都不在formula_45中。为此，定义formula_86为formula_80中一条从formula_88到formula_89的边，则若formula_90，那么有formula_91。（反证）假设formula_92但formula_93；由于formula_94是一个匹配边的末端点，formula_95，因此存在从formula_41到formula_94的有向路径。这条路径必不能经过formula_98（根据假设），因此这条路径上紧邻formula_94的点是其他点formula_100。formula_101是一条从formula_88到formula_89的紧边因此也是formula_80中的一个元素。但因此formula_80包含两条有共点的边，与formula_80是匹配的定义矛盾。因此formula_80中每条边的两个顶点要么都在formula_45中，要么都不在formula_45中。
证明formula_79在更改之后是势函数，等价于证明不存在总势超过成本的边。这已经在之前的论述中已经为formula_80中的边建立这个概念，因此我们考虑任意从formula_89到formula_88的边formula_115。如果formula_116升高了formula_54，那么：(1)formula_118，在这种情况下，formula_119减小了formula_54，使总体的势未发生改变；(2)formula_121，这种情况下formula_54的定义保证了formula_123。因此formula_79仍然是势函数。
给定 formula_125 个工人和任务，以及一个包含分配给每个工人一个任务的成本的 formula_126矩阵，寻找成本最小化分配。
首先把问题写成下面的矩阵形式
其中 formula_128是执行任务 1, 2, 3, 4 的工人。formula_129 分别表示当工人 formula_130 做任务 1, 2, 3, 4 时的时间损失（成本）。对于其他符号也同样适用。该矩阵是方阵，所以每个工人只能执行一个任务。
第 1 步
接下来我们对矩阵的行进行操作。将所有 formula_131 （formula_4 从 1 到 4）中最小的元素取走，并将该行每个元素都减去刚刚取走的元素。这会让该行至少出现一个零（当一行有两个相等的最小元素时会得到多个零）。对此过程为所有行重复。我们现在得到一个每行至少有一个零的矩阵。现在我们尝试给工人指派任务，以使每个工人只做一项任务，并且每个情况的耗散都为零。说明如下。
用 0' 表示的零为已指派的任务。
第 2 步
有时此阶段的该矩阵不能符合指派的要求，例如下面所示矩阵。
在上述情形下，不能做出指派。注意到任务 1 由工人 formula_133 和 formula_134 做都很高效。只是不能把两个工人分配到同一个任务中去。还注意到，没有任何一个工人能有效地做任务 3。 为了克服这个问题，我们对所有列重复上述流程（即每一列所有元素都减去该列最小元素）并检查是否可以完成分配。
大多数情况下，这都会给出结果，但如果仍然是不可行，那么我们需要继续下去。
第 3 步
必须用尽可能少的列或行标记来覆盖矩阵中的所有零。下面的过程是完成这个要求的一种方法：
首先，尽可能多地分配任务。或者，分配的是第 3 行的 0，就会使第 1 行的 0 被划掉。
现在到了画图的部分。
现在劃掉所有已标记的列和未标记的行（第 1 列和第 2, 4 行）。
上述详细的描述只是画出覆盖所有 0 的（直、行）线的一种方法。也可以使用其他方法。
第 4 步
现在删除已畫線的行和列。这将留下一个矩阵如下：
返回到步骤 1，然后重复这个过程，直到矩阵是空的。 （请注意，并非所有这些都满足 formula_2 时间约束。）