想象你是公司里的「团建活动总导演」,要把同事们两两组队参加双人项目。规则只有一条:每个人只能出现在一支队伍里。你的目标是用有限的人,组建出尽可能多的队伍。这正是图论中「匹配」问题的原型——把人与人之间的合作意愿看成边,把「不冲突的组队方案」看成匹配,而「最多能组几队」就是最大匹配。 不过事情没那么简单。光靠「先到先得」抢人,往往拿不到最优方案;有时为了多组一队,还得拆散已经组好的队伍重新洗牌。这背后藏着一套精妙的「增广路径」理论。顺着这条线索,我们会认识专门解决男女配对问题的匈牙利算法、追求总收益最大化的KM算法,以及连「三角恋死循环」都能处理的Blossom开花算法。读完这篇文章,你会像一位经验丰富的总导演一样,一眼看出最优组队方案,还能把这个能力迁移到任务指派、资源调度的真实场景中。
图匹配是组合优化与网络算法的基石工具。掌握最大匹配与最优匹配的求解思想,是AI从业者把抽象图模型落地为调度、指派、推荐等现代系统优化方案的核心能力。
可视化演示
展示图匹配三大核心:二部图匹配、增广路径交替路、Kuhn-Munkres最优权匹配,通过动态网络图演示匹配过程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
二部图最大匹配 左右两侧节点寻找一一对应关系 绿色边为已匹配边,粒子沿匹配流动 匈牙利算法核心
匹配定义与性质
团建总导演的第一件事,是搞清楚什么叫「合格」的组队方案。假如同事之间有6条合作意愿边,你不可能全安排——因为每个员工分身乏术。合格的方案只能挑出一些边,保证「没有两条边共用同一个人」。这就是匹配的本质:从边集中挑出互不打架的边。
在数学上,图 \( G=(V,E) \) 的一个匹配 \( M \),就是满足「任意两条边都没有公共端点」的边集。最大匹配是边数最多的匹配,完美匹配则是让每个顶点都被匹配边覆盖的匹配——相当于所有人都组上了队,一个不落。注意,不是所有图都有完美匹配,正如不是每次团建都能全员上阵。
1. 边集选取:匹配 \( M \) 是从原图所有边中挑出的一个子集
2. 两两不相交:任意两条匹配边 \( e_i \) 与 \( e_j \) 没有公共端点,用交集为空表示
3. 边数上界:每条边消耗2个顶点,所以匹配边数最多是顶点数的一半
回到团建:匹配是「每人只参与一队」的纪律,最大匹配是「在不违反纪律的前提下组出最多队伍」,而完美匹配是「全体成员都找到了队伍」。理解了这个基础,接下来要解决的关键问题就是:如何系统性地让队伍数量一步步逼近上限。
增广路径定理
现在的组队方案是 \( M \)(比如2队),你想再塞进一队,但所有人都已经被安排了。总导演的经验是:不要硬抢,试着让两对组合「串一串」。比如小张和小李搭档、小王和小赵搭档,如果小张其实更想和小赵搭档,小李又闲着没组上,就能形成一条「换人链」,让整体队伍数量+1。
这条「换人链」在数学上叫增广路径。它是一条路径,边在「非匹配边—匹配边—非匹配边—匹配边」之间交替出现,并且路径的两端都是未匹配顶点。沿着这条路径,把匹配边和非匹配边全部互换——也就是对路径做对称差运算——队伍数量就会增加1。图 \( G \) 的匹配 \( M \) 是最大匹配,当且仅当 \( G \) 中不存在关于 \( M \) 的增广路径。 这就是增广路径定理,整个最大匹配算法的理论基石。
1. 交替特征:路径上的边交替属于 \( M \) 与不属于 \( M \),不能连续两条同为匹配边或同为非匹配边
2. 两端空闲:路径的起点 \( v_0 \) 与终点 \( v_t \) 都是未匹配顶点,这是「能新塞一队」的前提
3. 对称差操作:把路径上的边全部「取反」——原来的匹配边变为非匹配边,非匹配边变为匹配边
4. 数量加一:路径上非匹配边比匹配边多一条,取反后匹配边总数净增1
增广路径就像团建排班里的「连锁调整」:只要有人愿意调整搭档,就总能多组一队。而增广路径定理保证了这一策略的完备性——当所有连锁调整都尝试过仍无法新增队伍时,你手里的方案就是全局最优。那么具体如何系统性地找到增广路径呢?这就轮到匈牙利算法登场了。
匈牙利算法
匈牙利算法的思路,像一个「先到先得 + 及时让位」的排班系统。算法从左边的未匹配顶点出发,用深度优先搜索(DFS)或广度优先搜索(BFS)尝试寻找增广路径。每找到一个未匹配的右顶点,就尝试把它占下;如果这个右顶点已经被匹配,就递归地让它的搭档「再去找别的右顶点」,也就是腾位。
这个过程会形成一棵交替搜索树:树的根是未匹配左顶点,往下交替走「非匹配边—匹配边」。如果树中某个未匹配右顶点被探到,就说明找到了一条增广路径;此时沿路径做对称差更新匹配,匹配数+1。对每个左顶点重复这一过程,直到没有增广路径可找。因为每轮增广至少增加一条匹配边,而匹配数上界是 \( \lfloor n/2 \rfloor \),加上DFS本身要遍历 \( O(E) \) 条边,总复杂度为 \( O(VE) \)。
1. 逐一尝试:依次从每个未匹配的左顶点出发,把它当作搜索树的根
2. 递归腾位:DFS 访问右顶点 \( v \),若 \( v \) 未匹配则找到增广路径;若已匹配给 \( u' \),则递归让 \( u' \) 另寻他路
3. 访问标记:每轮 DFS 维护 \( \text{visited} \),避免重复搜索形成死循环
4. 匹配数增长:每找出一条增广路径,匹配边数加1,直到不存在增广路径
匈牙利算法完美继承了增广路径定理的「体检报告」逻辑:每一轮要么找到增广路径让匹配更优,要么证明该顶点已无路可增广。它的局限也很明显——只适用于二部图,因为一旦图中有奇环(如三角形),递归可能陷入同一批顶点的循环。这个坑,要等Blossom算法来填。先把二部图问题彻底解决,我们再谈带权的最优匹配——KM算法。
KM最优匹配
团建总导演渐渐不满足于「队伍最多」——他开始关心总产出:每对搭档合作能创造不同的价值,他希望让总价值最大。这正是最优匹配(带权匹配)问题,Kuhn-Munkres算法(简称KM)是它的经典解法。KM算法的妙招是给每个顶点发一张「能力标价牌」,规则是左顶标 \( l(x) \) 加右顶标 \( l(y) \) 必须不低于两人合作的收益 \( w(x,y) \),这叫可行顶标。
在所有边中,只保留「标价刚好等于收益」的边,这些边组成相等子图。可以证明:若相等子图中存在完备匹配,那么这个匹配一定是最优匹配,且总收益恰好等于所有顶标之和。如果当前相等子图找不到完备匹配,就适当降低某些左顶标、提高某些右顶标,让更多边进入相等子图,直到找到完备匹配为止。KM算法通过反复增广和调整顶标,保证在 \( O(n^3) \) 时间内得到最优解。
1. 可行顶标:左顶点 \( x \) 与右顶点 \( y \) 的顶标之和不小于边权,保证顶标是「不虚高」的上界
2. 相等子图:只保留满足 \( l(x)+l(y)=w(x,y) \) 的边
3. 完备匹配判定:在相等子图中寻找覆盖所有顶点的完美匹配
4. 最优性证明:任意匹配 \( M \) 的总权不超过顶标总和,而 \( M^* \) 恰好达到该和
KM算法的「标价牌」像相亲节目里的心动值:先给每个人打一个「理想分」,只撮合分数刚好互补的两人;撮合不齐时再微调分数,让更多候选者进入待选池。因为这套标价体系始终锁定了收益的上限,一旦凑齐完备配对,就同时拿到了「人数满员」和「收益最大」的双重最优。不过,无论是匈牙利还是KM,都默认图是二部图——如果同事之间的关系网出现「三角恋」式的奇环,又该怎么办?
Blossom奇环
当图不是二部图时,事情变得棘手。二部图里,每条交替路径从左部出发必然回到右部,永远「黑白分明」;而一般图中的奇环(比如三角形)会让交替搜索树从不同方向探到同一个顶点,迭代陷入死循环——就像团建排班时三个人互相盯上了对方搭档,怎么调整都出不来新方案。
Edmonds在1965年给出了天才解法:把奇环整体收缩成一个「花苞」(Blossom)。奇环内部无论怎么匹配,一定恰好剩一个未匹配顶点(因为奇环顶点数为奇数),所以收缩后用一个超级顶点代替整个环,继续在外层跑增广路径;一旦找到增广路径,再展开花苞、还原环内的匹配细节。这个过程叫开花算法,成功把一般图最大匹配拉回多项式时间。
1. 奇环识别:交替搜索树中,若同一顶点被两条不同路径到达,且形成长度为奇数的环
2. 收缩操作:将整个奇环压缩为一个超级顶点 \( b \),环外部边全部连到 \( b \)
3. 匹配数量守恒:环内部最多匹配 \( \lfloor |B|/2 \rfloor \) 对,收缩图与原图最大匹配数相差这个值
4. 展开还原:外部增广完成后,把超级顶点还原成环,并按交替规则补全内部匹配
Blossom算法相当于给总导演配了一个「矛盾仲裁器」:遇到三角纠结就暂时把这几个人看作一个整体单元,先解决外部大局;大局落定后再回到内部细抠。正是这个「收缩—搜索—展开」三部曲,让最大匹配从二部图扩展到任意图,理论基础由此完备。有了这套完整工具箱,我们终于可以回答最初的问题——这些算法能解决哪些真实世界的难题?
匹配应用场景
学完了四种「组队策略」,总导演身份直接切换成各行各业的「资源调度官」。最典型的场景是指派问题:有 \( n \) 个任务和 \( n \) 个人,第 \( i \) 个人做第 \( j \) 个任务需花费 \( c_{ij} \),要让总成本最小。把任务和人分别看作二部图两侧顶点,成本看作边权,就跑一趟KM算法——这正是很多排班软件、物流配送系统的内核。
调度问题同样天然是匹配模型:云计算要把GPU设备分配给计算任务,直播平台要把转码任务调度到空闲服务器,本质都是在「任务—资源」二部图上求最大匹配或最优匹配。竞赛和算法题中也常见它的变体,比如棋盘覆盖问题:用「多米诺骨牌」覆盖棋盘上可用的格子,每块骨牌占相邻两格,求最多覆盖多少——把每个可用格子看成一个顶点,相邻关系看成边,最大匹配直接给出答案。
1. 决策变量:\( x_{ij}=1 \) 表示把任务 \( j \) 指派给人员 \( i \),否则为0
2. 任务约束:每个任务恰好被一个人完成,所以每列求和为1
3. 人员约束:每个人恰好承担一个任务,所以每行求和为1
4. 目标函数:所有指派的总花费最小化
至此,从「如何定义合格组队」到「如何找最多队伍」,再到「如何让收益最大」和「如何处理三角恋死循环」,我们用团建组队这条主线把图匹配的整个知识版图走了一遍。这些算法并非纸上谈兵——它们正在无数调度系统中默默运行,帮人类在纷繁复杂的资源约束里寻找那个最优解。
AI 应用场景
云端GPU任务调度
阶段:模型推理与训练的资源调度层
解决的问题:AI平台每天要处理成千上万个推理请求,每个请求可被多个异构GPU执行但延迟不同。传统FIFO排队导致高延迟任务积压,GPU利用率也低。将「推理任务—GPU实例」建模为二部图,用匈牙利算法求最大匹配——优先把更多任务安排进GPU;若还要考虑SLA权重和能耗,则升级为带权最优匹配(KM算法),在有限算力下让整体服务质量最大化。
具体案例:某AI视频平台需要把转码任务分配到空闲GPU卡。每张卡同时只能跑一个任务,且不同卡执行同一任务耗时不同。平台把每时段的任务与GPU建图,边权为预估完成时间,跑KM算法求最优指派,使整批任务的加权完成时间降低约32%。
外卖平台的骑手订单指派
阶段:即时配送系统的订单分配引擎
解决的问题:午高峰上百个外卖订单同时到达,骑手运力有限,每个骑手一次只能送一单,且配送距离不同导致成本不同。传统「就近分配」只顾局部最优,容易让部分骑手空跑、订单超时。把订单与骑手建模为二部图,边权 = 预计配送时长 × 超时风险系数,用KM算法求总成本最小的完备指派,同时用匈牙利算法的增广路径思想快速应对动态入单——新订单到来时不必全量重算,只需沿着增广路径做局部调整。
具体案例:美团类配送调度系统在高峰期将订单—骑手匹配建模为最优匹配问题,结合实时路况计算边权,每5秒滚动求解一次,使超时率下降18%,骑手空驶里程减少12%。
大模型训练下的数据并行切分
阶段:分布式训练中的数据与设备规划
解决的问题:大模型分布式训练需要把不同数据分片分配给多张GPU,且通信开销因设备拓扑不同而异。通过二部图匹配(数据分片—设备节点),边权为通信延迟,用KM算法求解「通信最优」的分配方案;当设备数量不足时,用最大匹配先判断能否覆盖全部数据分片,再配合Blossom算法处理非二部约束的特殊拓扑结构。
具体案例:某AI实验室训练千亿参数模型,64张GPU组成环形拓扑。通过最优匹配切分数据与流水线阶段,通信瓶颈降低25%,训练吞吐提升近两成。
Python 演示
def dfs(u, adj, match_r, seen): for v in adj[u]: if seen[v]: continue seen[v] = True if match_r[v] == -1 or dfs(match_r[v], adj, match_r, seen): match_r[v] = u return True return False def max_matching(n_left, n_right, edges): adj = [[] for _ in range(n_left)] for u, v in edges: adj[u].append(v) match_r = [-1] * n_right cnt = 0 for u in range(n_left): seen = [False] * n_right if dfs(u, adj, match_r, seen): cnt += 1 return cnt, match_r def perfect_matching_exists(n_left, n_right, cnt): if n_left != n_right: return False return cnt == n_left if __name__ == "__main__": # 二部图: 左侧3个任务, 右侧3台机器 # 边表示任务u可以被机器v执行 edges = [ (0, 0), (0, 1), (1, 1), (1, 2), (2, 1), (2, 2), ] n = 3 cnt, match_r = max_matching(n, n, edges) print("maximum matching size:", cnt) for r, u in enumerate(match_r): if u != -1: print("task %d -> machine %d" % (u, r)) print("perfect matching exists:", perfect_matching_exists(n, n, cnt))
def dfs(u, adj, match_r, seen):递归搜索增广路径,u是当前尝试匹配的左顶点,adj是每个左顶点的可连右顶点列表if match_r[v] == -1 or dfs(match_r[v], adj, match_r, seen):核心「让位」逻辑:若右顶点v空闲则直接占用;否则递归地让v当前的搭档另寻他路match_r[v] = u腾位成功后,把右顶点v匹配给u,匹配关系更新for u in range(n_left):依次为每个左顶点寻找增广路径,每成功一次匹配数加1seen = [False] * n_right每轮新搜索都重置访问标记,防止递归在同一轮内绕圈cnt == n_left若匹配数等于左顶点数,说明所有任务都被分配,构成完美匹配
常见误区
误区贪心算法随便挑边,直到没法再添加任何边,得到的匹配边数一定最多。既然「已经塞不下更多队伍了」,那不就是最大匹配吗?
正解极大匹配只是「局部最优」——你无法再直接添加一条边;但最大匹配是「全局最优」——所有匹配方案中边数最多。就好比团建时ABCD四人两两组队,贪心先让A和B一组、C和D一组,虽然是2队;但换个分法A和C、B和D还是2队;可如果贪心让A和B绑死,而C、D、E三人其实能组成更多队的三角关系,贪心就会漏掉最优。最大匹配必须借助增广路径不断调整,不是简单塞边能解决的。
为何常见:贪心的直觉太强——「放不下更多了」听起来就像最优。人们容易忽略增广路径带来的「换人」可能性,而正是这种连锁调整才能逼近全局最优。
误区匈牙利算法是求最大匹配的通用算法,不管图是不是二部图都能用,遇到奇环无非是搜索路径绕一点。
正解匈牙利算法只适用于二部图。它依赖「左部—右部」的交替结构,搜索才不会重访顶点;一旦遇到奇环(三角形),交替路径会从两个方向探到同一顶点,DFS腾位会无限循环或得出错误结果。处理一般图必须用Edmonds的Blossom算法——把奇环收缩成花苞再搜索。就像排班时三个人互为搭档死锁,你得先把这三人圈成「一个小组」处理,而不是让算法在三人间空转。
为何常见:教材和博客通常只讲二部图场景,很多初学者根本没接触过非二部图的反例,误以为「图」就是「二部图」。
误区只要一条路径的两端是未匹配点,中间随便走几条边,它就叫增广路径,就能让匹配数增加。
正解增广路径有严格结构:路径上的边必须严格「非匹配—匹配—非匹配—匹配」交替,且两端是未匹配顶点。只有在这种交替结构下做对称差,匹配边数才会恰好+1;如果路径上有连续两条边都属于匹配或都不属于匹配,交换后会出现顶点冲突或匹配数不增。好比换人链必须严格按「当前搭档—潜在新搭档—当前搭档」交替才能推进,中间断了一环就串不起来。
为何常见:把「增广」直观理解为「加点边」,忽略了交替性是保证「不冲突且数量+1」的关键,这是最容易被忽视的结构约束。
误区把KM算法代码拿过来,对任意二部图、任意边权矩阵都能直接运行,得到的就一定是最大权匹配。
正解经典KM算法要求图是完备二部图(左右顶点数相同且任意两点间有边),因为它的正确性依赖「可行顶标总和 = 最优匹配权值」的对偶关系,而这一关系在非完备图上不成立。处理稀疏图,惯例是给缺失边补上权值为0(或负无穷)的虚拟边,再保证左右顶点数对齐。如果不补边,算法可能误判「找不到完备匹配」。就像相亲节目必须让每位嘉宾都有心动名单,名单缺人就得空位补「零分」候选,否则配对流程无法完整进行。
为何常见:很多教程直接给 w[i][j] 矩阵,没解释矩阵本身的完备性要求;实战中直接拿稀疏图套代码,结果自然出错。
误区二部图左部有4个点右部有2个点,那最大匹配一定能把右部2个点全部匹配上;甚至左部4个右部4个时,最大匹配一定是完美匹配。
正解最大匹配的大小受边结构限制,不是顶点数量说了算。比如右部某个顶点没有任何边相连,它永远无法被匹配;左部4点右部4点的图也可能最大匹配只有2。判断能否全覆盖,需要Hall定理或者直接计算最大匹配数并与较小部顶点数比较。组队的根本约束是「有人愿意跟谁组队」,没有合作意愿的边,人数再多也白搭。
为何常见:大脑常把「顶点数」当成本质约束,忽略了「边是否存在」这个前提。匹配问题中,边才是决定上限的真正瓶颈。
面试题
Q1. 以下关于图中匹配的说法,正确的是?
- A.匹配中的任意两条边可以有公共端点
- B.匹配是任意边组成的集合
- C.匹配中任意两条边没有公共端点← 正确答案
- D.匹配必须包含图中的所有顶点
答案:C。匹配的核心定义是「边集中任意两条边不相交」,即无公共端点,对应C。A是反面定义;B漏掉了「互不相交」的约束;D说的是完美匹配,普通匹配不需要覆盖所有顶点。好比团建组队时每个人只能参加一队,而不是某人可以同时出现在两支队伍里。
Q2. 一个图有10个顶点,其最大匹配的边数至多为多少?
- A.3
- B.4
- C.5← 正确答案
- D.10
答案:C。每条匹配边消耗2个不同顶点,所以匹配边数上限是顶点数的一半,即 ⌊10/2⌋=5。这是匹配的边数上界公式 \( |M|\le\lfloor n/2\rfloor \)。好比10个人组双人队,最多只能组5队,不可能组出6队。
Q3. 匈牙利算法不能直接求解以下哪种图的最大匹配?
- A.完全二部图
- B.稀疏二部图
- C.含奇环的一般图← 正确答案
- D.树形二部图
答案:C。匈牙利算法适用于二部图,包括完全二部图、稀疏二部图和树形二部图。但含奇环的一般图会让交替搜索树重复访问同一顶点、陷入死循环,必须改用Blossom算法。三角恋式的三个人互相指向对方,就是奇环对算法的致命干扰。
Q4. 关于增广路径,以下描述正确的是?
- A.路径上所有边都属于当前匹配
- B.路径上所有边都不属于当前匹配
- C.起点和终点都是未匹配顶点,且匹配边与非匹配边交替← 正确答案
- D.路径任意,只要边数大于匹配数即可
答案:C。增广路径要求边严格交替属于/不属于当前匹配,且两端点是未匹配顶点。C完整描述了这两个必要条件。A只有匹配边无法「增广」;B相当于一条普通非匹配路径;D忽略了交替结构和端点条件。
Q5. 对于一个当前匹配 M,若找到一条增广路径 P,下列说法正确的是?
- A.沿 P 做对称差后,匹配数增加 1← 正确答案
- B.对称差运算为 \( M\oplus P = (M\setminus P)\cup(P\setminus M) \)← 正确答案
- C.沿 P 交换后,P 上原来的匹配边变为非匹配边← 正确答案
- D.沿 P 交换后,所有顶点都会被匹配
答案:ABC。增广路径上非匹配边比匹配边多一条,对称差交换后匹配数+1(A对);对称差定义正是B;交换后路径上原匹配边变为非匹配边、原非匹配边变为匹配边(C对)。D错误——交换只保证匹配数+1,不保证达到完美匹配,除非原本就是最后一个未匹配顶点。
Q6. KM算法的可行顶标需要满足什么条件?
- A.\( l(x)+l(y)=w(x,y) \) 对所有边成立
- B.\( l(x)+l(y)\ge w(x,y) \) 对所有边成立← 正确答案
- C.\( l(x)+l(y)\le w(x,y) \) 对所有边成立
- D.\( l(x)\cdot l(y)=w(x,y) \) 对所有边成立
答案:B。可行顶标要求任意边两端顶标之和不小于边权,即 \( l(x)+l(y)\ge w(x,y) \)。「等于」只对相等子图中的边成立,而非所有边;「小于」会让顶标总和低于真实匹配权值,破坏最优性证明;D完全不符合定义。标价牌只能把组合价值标得「不低于」真实收益,才能锁定天花板。
Q7. 关于最大匹配与完美匹配的关系,下列说法正确的有?
- A.完美匹配一定是最大匹配← 正确答案
- B.最大匹配不一定是完美匹配← 正确答案
- C.若图有偶数个顶点,则一定存在完美匹配
- D.完美匹配要求匹配边覆盖所有顶点← 正确答案
答案:ABD。完美匹配覆盖所有顶点,边数达到 ⌊n/2⌋ 的上界,因此必然是最大匹配(A对);最大匹配可能达不到全覆盖,所以不一定是完美匹配(B对);完美匹配的定义就是覆盖所有顶点(D对)。C显然错误——偶数顶点只是必要条件,图结构不满足时照样没有完美匹配。
Q8. 贪心算法得到的极大匹配,与最大匹配的关系是?
- A.两者一定相等
- B.极大匹配的边数一定不少于最大匹配
- C.极大匹配的边数可能少于最大匹配← 正确答案
- D.两者一定无关
答案:C。极大匹配只是「无法再直接加边」的局部最优,而最大匹配是全局最优;极大匹配的边数可能少于最大匹配。比如贪心先占用了关键顶点,可能导致后续无法增广。增广路径的存在正是为了突破局部最优,这是从极大走向最大的关键。
Q9. 在Blossom算法中,遇到奇环后需要进行哪些操作步骤?
- A.将奇环收缩为一个超级顶点← 正确答案
- B.在收缩后的图上继续寻找增广路径← 正确答案
- C.找到增广路径后,展开超级顶点还原内部匹配← 正确答案
- D.直接将奇环中的所有边加入匹配
答案:ABC。Blossom算法的核心三步:收缩奇环为花苞(A)、在收缩图上继续搜索增广路径(B)、外部找到路径后展开花苞并补全内部匹配(C)。D错误——把奇环所有边都加入匹配会违反「无公共端点」的定义,奇环内部最多只能匹配 ⌊|B|/2⌋ 对。
Q10. 需要把 n 个任务分配给 n 个人员使总成本最小,且每个任务只能分配给一个人。最适合的算法是?
- A.匈牙利算法求最大匹配
- B.KM算法求最优匹配← 正确答案
- C.Blossom算法求最大匹配
- D.贪心按最小成本逐个分配
答案:B。这是典型带权完备指派问题,KM算法的可行顶标与相等子图机制正是为此设计,能在 \( O(n^3) \) 时间内保证总成本最小(B对)。匈牙利算法只求匹配数最多、不计权值(A错);Blossom处理非二部图最大匹配(C错);贪心逐个分配是局部最优,无法保证全局最小(D错)。