匹配问题与匈牙利算法和较大基数匹配
- 格式:pdf
- 大小:136.34 KB
- 文档页数:7
匈⽛利算法解决⼆分图最⼤匹配预备知识 匈⽛利算法是由匈⽛利数学家Edmonds于1965年提出,因⽽得名。
匈⽛利算法是基于Hall定理中充分性证明的思想,它是⼆分图匹配最常见的算法,该算法的核⼼就是寻找增⼴路径,它是⼀种⽤增⼴路径求⼆分图最⼤匹配的算法。
⼆分图 ⼆分图⼜称作⼆部图,是图论中的⼀种特殊模型。
设G=(V,E)是⼀个⽆向图,如果顶点V可分割为两个互不相交的⼦集(A,B),并且图中的每条边(i,j)所关联的两个顶点 i 和 j 分别属于这两个不同的顶点集(i in A,j in B),则称图G为⼀个⼆分图。
匹配 在图论中,⼀个图是⼀个匹配(或称独⽴边集)是指这个图之中,任意两条边都没有公共的顶点。
这时每个顶点都⾄多连出⼀条边,⽽每⼀条边都将⼀对顶点相匹配。
例如,图3、图4中红⾊的边就是图2的匹配。
图3中1、4、5、7为匹配点,其他顶点为⾮匹配点,1-5、4-7为匹配边,其他边为⾮匹配边。
最⼤匹配 ⼀个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最⼤匹配。
图 4 是⼀个最⼤匹配,它包含 4 条匹配边。
任意图中,极⼤匹配的边数不少于最⼤匹配的边数的⼀半。
完美匹配 如果⼀个图的某个匹配中,所有的顶点都是匹配点,那么它就是⼀个完美匹配。
显然,完美匹配⼀定是最⼤匹配,但并⾮每个图都存在完美匹配。
最⼤匹配数:最⼤匹配的匹配边的数⽬。
最⼩点覆盖数:选取最少的点,使任意⼀条边⾄少有⼀个端点被选择。
最⼤独⽴数:选取最多的点,使任意所选两点均不相连。
最⼩路径覆盖数:对于⼀个DAG(有向⽆环图),选取最少条路径,使得每个顶点属于且仅属于⼀条路径,路径长可以为0(即单个点)定理1:Konig定理——最⼤匹配数 = 最⼩点覆盖数定理2:最⼤匹配数 = 最⼤独⽴数定理3:最⼩路径覆盖数 = 顶点数 - 最⼤匹配数匈⽛利算法例⼦ 为了便于理解,选取了dalao博客⾥找妹⼦的例⼦: 通过数代⼈的努⼒,你终于赶上了剩男剩⼥的⼤潮,假设你是⼀位光荣的新世纪媒⼈,在你的⼿上有N个剩男,M个剩⼥,每个⼈都可能对多名异性有好感(惊讶,-_-||暂时不考虑特殊的性取向) 如果⼀对男⼥互有好感,那么你就可以把这⼀对撮合在⼀起,现在让我们⽆视掉所有的单相思(好忧伤的感觉,快哭了),你拥有的⼤概就是下⾯这样⼀张关系图,每⼀条连线都表⽰互有好感。
二分图的最大匹配、完美匹配和匈牙利算法August 1, 2013 / 算法这篇文章讲无权二分图(unweighted bipartite graph)的最大匹配(maximum matching)和完美匹配(perfect matching),以及用于求解匹配的匈牙利算法(Hungarian Algorithm);不讲带权二分图的最佳匹配。
二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。
准确地说:把一个图的顶点划分为两个不相交集U和V,使得每一条边都分别连接U、V中的顶点。
如果存在这样的划分,则此图为一个二分图。
二分图的一个等价定义是:不含有「含奇数条边的环」的图。
图 1 是一个二分图。
为了清晰,我们以后都把它画成图 2 的形式。
匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。
例如,图3、图 4 中红色的边就是图 2 的匹配。
我们定义匹配点、匹配边、未匹配点、非匹配边,它们的含义非常显然。
例如图 3 中 1、4、5、7 为匹配点,其他顶点为未匹配点;1-5、4-7为匹配边,其他边为非匹配边。
最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
图 4 是一个最大匹配,它包含 4 条匹配边。
完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。
图 4 是一个完美匹配。
显然,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。
但并非每个图都存在完美匹配。
举例来说:如下图所示,如果在某一对男孩和女孩之间存在相连的边,就意味着他们彼此喜欢。
是否可能让所有男孩和女孩两两配对,使得每对儿都互相喜欢呢?图论中,这就是完美匹配问题。
如果换一个说法:最多有多少互相喜欢的男孩/女孩可以配对儿?这就是最大匹配问题。
基本概念讲完了。
二分图匹配题目类型总结二分图最大匹配的匈牙利算法二分图是这样一个图,它的顶点可以分类两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y。
最大匹配:图中包含边数最多的匹配称为图的最大匹配。
完美匹配:如果所有点都在匹配边上(x=y=m),称这个最大匹配是完美匹配。
最小点覆盖:(二分图)最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。
可以证明:最少的点(即覆盖数)=最大匹配数。
支配集:(二分图)最小点覆盖数+孤立点最小边覆盖:找最大匹配(注意可能是任意图最大匹配)m则有2*m 个点被m 条两两不相交的边覆盖。
对于剩下的n-2*m 个点,每个点用一条边覆盖,总边数为n-m条;最小路径覆盖:用尽量少的不相交简单路径覆盖有向无环图G的所有结点。
解决此类问题可以建立一个二分图模型。
把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。
最大独立集问题:(二分图)n-最小点覆盖;任意图最大匹配:(没有奇环)转换为二分图:把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果原图中有边i->j,则在二分图中引入边i-> j',j->i’;设二分图最大匹配为m,则结果就是m/2。
最大完全子图:补图的最大独立集三大博弈问题威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
这种情况下是颇为复杂的。
我们用(ak,bk)(ak ≤bk ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。
前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。
前言:高中时候老师讲这个就听得迷迷糊糊,有一晚花了通宵看KM的Pascal代码,大概知道过程了,后来老师说不是重点,所以忘的差不多了。
都知道二分图匹配是个难点,我这周花了些时间研究了一下这两个算法,总结一下1.基本概念M代表匹配集合未盖点:不与任何一条属于M的边相连的点交错轨:属于M的边与不属于M的边交替出现的轨(链)可增广轨:两端点是未盖点的交错轨判断M是最大匹配的标准:M中不存在可增广轨2.最大匹配,匈牙利算法时间复杂度:O(|V||E|)原理:寻找M的可增广轨P,P包含2k+1条边,其中k条属于M,k+1条不属于M。
修改M 为M&P。
即这条轨进行与M进行对称差分运算。
所谓对称差分运算,就是比如X和Y都是集合,X&Y=(X并Y)-(x交Y)有一个定理是:M&P的边数是|M|+1,因此对称差分运算扩大了M实现:关于这个实现,有DFS和BFS两种方法。
先列出DFS的代码,带注释。
这段代码来自中山大学的教材核心部分在dfs(x),来寻找可增广轨。
如果找到的话,在Hungarian()中,最大匹配数加一。
这是用了刚才提到的定理。
大家可以想想初始状态是什么,又是如何变化的view plaincopy to clipboardprint?第二种方法BFS,来自我的学长cnhawk核心步骤还是寻找可增广链,过程是:1.从左的一个未匹配点开始,把所有她相连的点加入队列2.如果在右边找到一个未匹配点,则找到可增广链3.如果在右边找到的是一个匹配的点,则看它是从左边哪个点匹配而来的,将那个点出发的所有右边点加入队列这么说还是不容易明白,看代码吧view plaincopy to clipboardprint?3.最佳匹配加权图中,权值最大的最大匹配KM算法:概念:f(v)是每个点的一个值,使得对任意u,v C V,f(u)+f(v)>=w[e u,v]集合H:一个边集,使得H中所有u,v满足f(u)+f(v)=w[e u,v]等价子图:G f(V,H),标有f函数的G图理论:对于f和G f,如果有一个理想匹配集合M p,则M p最优。
指派问题匈牙利算法最大值
指派问题是一个优化问题,旨在确定如何将 n 个任务分配给 n 个人员,以便完成总成本最小或总利润最大。
匈牙利算法是解决指派问题的经典算法之一,通过寻找增广路径来找到最大权值的匹配。
在指派问题中,我们有一个 n x n 的成本矩阵,其中的每个元素表
示将特定任务分配给特定人员的成本或利润。
问题的目标是找到一种分配方式,使得总成本最小或总利润最大。
匈牙利算法是一种基于图论的算法,它通过构建二分图和寻找增广路径来解决指派问题。
算法的核心思想是通过不断改进当前的匹配,直到找到最优解。
具体来说,匈牙利算法的步骤如下:
1. 初始化一个空的匹配集合。
2. 对于每个任务,找到一个未被分配的人员,并将其分配给该任务。
如果该任务没有未被分配的人员,则考虑将其他任务分配给当前人员,并将当前任务分配给其它人员。
3. 如果存在一个未被匹配的任务,寻找一条从该任务出发的增广路径。
增广路径是一条交替经过匹配边和非匹配边的路径,起点和终点都是未匹配的任务。
4. 如果存在增广路径,则改进当前的匹配,即通过将增广路径上的
非匹配边变为匹配边,并将增广路径上的匹配边变为非匹配边。
5. 重复步骤3和步骤4,直到不存在增广路径为止。
匈牙利算法的运行时间复杂度为 O(n^3),其中 n 是任务或人员的数量。
该算法可以找到指派问题的最优解,并且在实践中表现良好。
总之,指派问题是一个重要的优化问题,而匈牙利算法是一种解决指派问题的经典算法。
通过构建二分图并寻找增广路径,匈牙利算法可以找到指派问题的最优解。
python实现匈⽛利算法求解⼆分图最⼤匹配重点:理解和取反1. 匈⽛利算法求解⽬标:找到⼆分图的最⼤匹配整体思路:每⼀步寻找⼀条增⼴路径,取反2. 关键步骤⼆分图的顶点分为左边点集X和右边点集Y,假定遍历的点集是X。
对于每⼀次迭代的点x_i,1. 搜索增⼴路径:遍历x_i的邻接节点y_j1. 如果y_j未匹配,则找到增⼴路2. 如果y_j已匹配,则寻找y_j的匹配节点的增⼴路径(深搜或者⼴搜)2. 取反:把增⼴路径中的已经匹配边改成未匹配;未匹配的改成匹配3. python代码算法输⼊为字典形式的特殊邻接表。
特殊之处在于字典的键和值的顶点分别属于⼆分图的左右点集合。
深度搜索增⼴路径函数的参数中的visited_set的作⽤是避免重复访问。
# 匈⽛利算法(dfs)class Hungarian:def search_extend_path(self, l_node, adjoin_map, l_match, r_match, visited_set):'''深度搜索增⼴路径'''for r_node in adjoin_map[l_node]: # 邻接节点if r_node not in r_match.keys(): # 情况1:未匹配, 则找到增⼴路径,取反l_match[l_node] = r_noder_match[r_node] = l_nodereturn Trueelse: # 情况2: 已匹配next_l_node = r_match[r_node]if next_l_node not in visited_set:visited_set.add(next_l_node)if self.search_extend_path(next_l_node, adjoin_map, l_match, r_match, visited_set): # 找到增⼴路径,取反l_match[l_node] = r_noder_match[r_node] = l_nodereturn Truereturn Falsedef run(self, adjoin_map):''':param adjoin_map: {x_i: [y_j, y_k]}:return:'''l_match, r_match = {}, {} # 存放匹配for lNode in adjoin_map.keys():self.search_extend_path(lNode, adjoin_map, l_match, r_match, set())return l_match。
一、概述匈牙利算法是一种用于求解二分图最大匹配的经典算法,它的时间复杂度为O(n^3),在实际应用中具有广泛的用途。
本文将通过一个具体的例题,详细介绍利用匈牙利算法求解完美匹配的具体步骤和方法。
二、问题描述假设有一个二分图G=(V, E),其中V={U,V},U={u1,u2,u3},V={v1,v2,v3},E={(u1,v1),(u1,v2),(u2,v2),(u3,v3)},现在希望求解这个二分图的最大匹配。
三、匈牙利算法详解1. 初始化:需要初始化一个大小为|U|的数组match[],用来记录每一个U中的顶点匹配的V中的顶点,初始化为-1,表示初始时没有匹配的顶点。
2. 寻找增广路径:通过遍历U中的每一个顶点,逐个寻找增广路径。
对于每一个未匹配的顶点,都尝试进行增广路径的寻找。
3. 匹配顶点:如果找到了一条增广路径,将增广路径上的顶点逐个匹配,并更新match[]数组。
4. 寻找最大匹配:重复上述步骤,直至无法继续寻找增广路径为止,此时match[]数组中记录的就是二分图的最大匹配。
四、具体例题求解接下来通过一个具体的例题来详细介绍匈牙利算法的求解过程。
假设有一个二分图G=(V, E),其中V={U,V},U={u1,u2,u3},V={v1,v2,v3},E={(u1,v1),(u1,v2),(u2,v2),(u3,v3)}。
首先初始化match[]数组为{-1,-1,-1}。
(1)对u1进行增广路径的寻找由于u1未匹配,从u1开始寻找增广路径。
首先考虑与u1相连的v1和v2。
对v1进行匹配,得到match[0]为1。
对v2进行匹配,得到match[0]为1。
(2)对u2进行增广路径的寻找由于u2未匹配,从u2开始寻找增广路径。
考虑与u2相连的v2。
对v2进行匹配,得到match[1]为2。
(3)对u3进行增广路径的寻找由于u3未匹配,从u3开始寻找增广路径。
考虑与u3相连的v3。
对v3进行匹配,得到match[2]为3。