图的匹配——匈牙利算法与KM算法

合集下载

KM算法

KM算法

int w[maxn][maxn];
int lx[maxn]={0},ly[maxn]={0}; //顶标
int linky[maxn];
int visx[maxn],visy[maxn];
int lack;
bool find(int x){
visx[x]=true;
现在的问题就是求d值了。为了使A[ i ]+B[j]>=w[i,j]始终成立,且至少有一条边进入相等子图,d应该等于:
Min{A[ i ]+B[j]-w[i,j] | Xi在交错树中,Yi不在交错树中}。
·改进:
以上就是KM算法的基本思路。但是朴素的实现方法,时间复杂度为O(n4)——需要找O(n)次增广路,每次增广最多需要修改O(n)次顶标,每次修改顶标时由于要枚举边来求d值,复杂度为O(n2)。实际上KM算法的复杂度是可以做到O(n3)的。我们给每个Y顶点一个“松弛量”函数slack,每次开始找增广路时初始化为无穷大。在寻找增广路的过程中,检查边(i,j)时,如果它不在相等子图中,则让slack[j]变成原值与A[ i ]+B[j]-w[i,j]的较小值。这样,在修改顶标时,取所有不在交错树中的Y顶点的slack值中的最小值作为d值即可。但还要注意一点:修改顶标后,要把所有的不在交错树中的Y顶点的slack值都减去d。
2)两端都不在交错树中的边(i,j),A[ i ]和B[j]都没有变化。也就是说,它原来属于(或不属于)相等子图,现在仍属于(或不属于)相等子图。
3)X端不在交错树中,Y端在交错树中的边(i,j),它的A[ i ]+B[j]的值有所增大。它原来不属于相等子图,现在仍不属于相等子图。
4)X端在交错树中,Y端不在交错树中的边(i,j),它的A[ i ]+B[j]的值有所减小。也就说,它原来不属于相等子图,现在可能进入了相等子图,因而使相等子图得到了扩大。

二分图匹配(匈牙利算法和KM算法)

二分图匹配(匈牙利算法和KM算法)

前言:高中时候老师讲这个就听得迷迷糊糊,有一晚花了通宵看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最优。

匈牙利算法和KM算法简介

匈牙利算法和KM算法简介

KM算法
❖ 穷举旳效率-n!,我们需要愈加优异旳算法。 ❖ 定理: ❖ 设M是一种带权完全二分图G旳一种完备匹配,给
每个顶点一种可行顶标(第i个x顶点旳可行标用lx[i] 表达,第j个y顶点旳可行标用ly[j]表达),假如对全 部旳边(i,j) in G,都有lx[i]+ly[j]>=w[i,j]成立(w[i,j]表达 边旳权),且对全部旳边(i,j) in M,都有lx[i]+ly[j]=w[i,j] 成立,则M是图G旳一种最佳匹配。证明很轻易。
KM算法
❖ 对于任意旳G和M,可行顶标都是存在旳:
❖ l(x) = maxw(x,y)
❖ l(y) = 0 ❖ 欲求完全二分图旳最佳匹配,只要用匈牙利算法求
其相等子图旳完备匹配;问题是当标号之后旳Gl无 完备匹配时怎么办?1957年(居然比匈牙利算法 早???),Kuhn和Munkras给出了一种处理该问 题旳有效算法,用逐次修改可行顶标l(v)旳方法使相 应旳相等子图之最大匹配逐次增广,最终出现完备 匹配。
KM算法
❖ 修改措施如下:
❖ 先将一种未被匹配旳顶点u(u in {x})做一次增广路, 记下哪些结点被访问那些结点没有被访问。求出 d=min{lx[i]+ly[j]-w[i,j]}其中i结点被访问,j结点没有 被访问。然后调整lx和ly:对于访问过旳x顶点,将 它旳可行标减去d,对于全部访问过旳y顶点,将它 旳可行标增长d。修改后旳顶标仍是可行顶标,原 来旳匹配M依然存在,相等子图中至少出现了一条 不属于M旳边,所以造成M旳逐渐增广。
Empty Grass Wall
例题1 Place the Robots(ZOJ)
模型一
在问题旳原型中,草地,墙这些信 息不是我们所关心旳,我们关心旳 只是空地和空地之间旳联络。所以, 我们很自然想到了下面这种简朴旳 模型:

算法学习:图论之二分图的最优匹配(KM算法)

算法学习:图论之二分图的最优匹配(KM算法)

二分图的最优匹配(KM算法)KM算法用来解决最大权匹配问题:在一个二分图内,左顶点为X,右顶点为Y,现对于每组左右连接XiYj有权wij,求一种匹配使得所有wij的和最大。

基本原理该算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。

设顶点Xi的顶标为A[ i ],顶点Yj的顶标为B[ j ],顶点Xi与Yj之间的边权为w[i,j]。

在算法执行过程中的任一时刻,对于任一条边(i,j),A[ i ]+B[j]>=w[i,j]始终成立。

KM算法的正确性基于以下定理:若由二分图中所有满足A[ i ]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。

首先解释下什么是完备匹配,所谓的完备匹配就是在二部图中,X点集中的所有点都有对应的匹配或者是Y点集中所有的点都有对应的匹配,则称该匹配为完备匹配。

这个定理是显然的。

因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和。

所以相等子图的完备匹配一定是二分图的最大权匹配。

初始时为了使A[ i ]+B[j]>=w[i,j]恒成立,令A[ i ]为所有与顶点Xi关联的边的最大权,B[j]=0。

如果当前的相等子图没有完备匹配,就按下面的方法修改顶标以使扩大相等子图,直到相等子图具有完备匹配为止。

我们求当前相等子图的完备匹配失败了,是因为对于某个X顶点,我们找不到一条从它出发的交错路。

这时我们获得了一棵交错树,它的叶子结点全部是X顶点。

现在我们把交错树中X顶点的顶标全都减小某个值d,Y顶点的顶标全都增加同一个值d,那么我们会发现:1)两端都在交错树中的边(i,j),A[ i ]+B[j]的值没有变化。

也就是说,它原来属于相等子图,现在仍属于相等子图。

2)两端都不在交错树中的边(i,j),A[ i ]和B[j]都没有变化。

BipartiteGraph

BipartiteGraph
1 2 3 4 5
1 2
5
3 4
1
2
3
4
由于每条边表示一个空地,有冲 突的空地之间必有公共顶点,所 以问题转化为二部图的最大匹配 问题。
1
2
3
4
例题1 Place the Robots(ZOJ)
小结
比较前面的两个模型:模型一过于简单,没有给问 题的求解带来任何便利;模型二则充分抓住了问题的内 在联系,巧妙地建立了二部图模型。为什么会产生这种 截然不同的结果呢?其一是由于对问题分析的角度不同: 模型一以空地为点,模型二以空地为边;其二是由于对 原型中要素的选取有差异:模型一对要素的选取不充分, 模型二则保留了原型中“棋盘”这个重要的性质。由此 可见,对要素的选取,是图论建模中至关重要的一步。
二分图匹配
匈牙利算法和KM算法简介
二分图的概念
二分图又称作二部图,是图论中的一种特殊
模型。 设G=(V,{R})是一个无向图。如顶点集V可分 割为两个互不相交的子集,并且图中每条边 依附的两个顶点都分属两个不同的子集。则 1 2 3 4 5 称图G为二分图。
1
2
3
4
最大匹配
给定一个二分图G,在G的一个子图M中,M
1
2 3
4
1 3 8 5 7 2
8 7 6 5
4
这是NP问题!
6
例题1 Place the Robots(ZOJ)
模型二
我们将每一行,每一列被墙隔开, 且包含空地的连续区域称作 “块”。显然,在一个块之中, 最多只能放一个机器人。我们把 这些块编上号。
1 2
5
3 4
同样,把竖直方向的块也编上号。
1
KM算法

二分图匹配--匈牙利算法

二分图匹配--匈牙利算法

⼆分图匹配--匈⽛利算法⼆分图匹配--匈⽛利算法⼆分图匹配匈⽛利算法基本定义:⼆分图 —— 对于⽆向图G=(V,E),如果存在⼀个划分使V中的顶点分为两个互不相交的⼦集,且每个⼦集中任意两点间不存在边 ϵ∈E,则称图G为⼀个⼆分图。

⼆分图的充要条件是,G⾄少有两个顶点,且所有回路长度为偶数。

匹配 —— 边的集合,其中任意两条边都不存在公共顶点。

匹配边即是匹配中的元素,匹配点是匹配边的顶点,同样⾮匹配边,⾮匹配点相反定义。

最⼤匹配——在图的所有匹配中,包含最多边的匹配成为最⼤匹配 完美匹配——如果在⼀个匹配中所有的点都是匹配点,那么该匹配称为完美匹配。

附注:所有的完美匹配都是最⼤匹配,最⼤匹配不⼀定是完美匹配。

假设完美匹配不是最⼤匹配,那么最⼤匹配⼀定存在不属于完美匹配中的边,⽽图的所有顶点都在完美匹配中,不可能找到更多的边,所以假设不成⽴,及完美匹配⼀定是最⼤匹配。

交替路——从⼀个未匹配点出发,依次经过⾮匹配边,匹配边,⾮匹配边…形成的路径称为交替路,交替路不会形成环。

增⼴路——起点和终点都是未匹配点的交替路。

因为交替路是⾮匹配边、匹配边交替出现的,⽽增⼴路两端节点都是⾮匹配点,所以增⼴路⼀定有奇数条边。

⽽且增⼴路中的节点(除去两端节点)都是匹配点,所属的匹配边都在增⼴路径上,没有其他相连的匹配边,因此如果把增⼴路径中的匹配边和⾮匹配边的“⾝份”交换,就可以获得⼀个更⼤的匹配(该过程称为改进匹配)。

⽰例图Fig1_09_09.JPG注释:Fig3是⼀个⼆分图G=(V,E),V={1,2,3,4,5,6,7,8},E={(1,7),(1,5),(2,6),(3,5),(3,8),(4,5),(4,6)},该图可以重绘成Fig4,V可分成两个⼦集V={V1,V2},V1={1,2,3,4},V2={5,6,7,8}。

Fig4中的红⾊边集合就是⼀个匹配{(1,5),(4,6),(3,8)}Fig2中是最⼤匹配Fig1中红⾊边集合是完美匹配Fig1中交替路举例(4-6-2-7-1-5)Fig4中增⼴路(2-6-4-5-1-7)匈⽛利树匈⽛利树中从根节点到叶节点的路径均是交替路,且匈⽛利树的叶节点都是匹配点。

二分图匹配――匈牙利算法和KM算法简介.

二分图匹配――匈牙利算法和KM算法简介.

KM算法
对于任意的G和M,可行顶标都是存在的: l(x) = maxw(x,y) l(y) = 0 欲求完全二分图的最佳匹配,只要用匈牙利算法求 其相等子图的完备匹配;问题是当标号之后的Gl无 完备匹配时怎么办?1957年(居然比匈牙利算法 早???),Kuhn和Munkras给出了一个解决该问 题的有效算法,用逐次修改可行顶标l(v)的办法使对 应的相等子图之最大匹配逐次增广,最后出现完备 匹配。
二分图匹配
匈牙利算法和KM算法简介
二分图的概念
二分图又称作二部图,是图论中的一种特殊
模型。 设G=(V,{R})是一个无向图。如顶点集V可分 割为两个互不相交的子集,并且图中每条边 依附的两个顶点都分属两个不同的子集。则 1 2 3 4 5 称图G为二分图。
1
2
3
4
最大匹配
给定一个二分图G,在G的一个子图M中,M
的边集{E}中的任意两条边都不依附于同一个 顶点,则称M是一个匹配。 选择这样的边数最大的子集称为图的最大匹 配问题(maximal matching problem) 如果一个匹配中,图中的每个顶点都和图中 某条边相关联,则称此匹配为完全匹配,也 称作完备匹配。
匈牙利算法
求最大匹配的一种显而易见的算法是:先找出全部 匹配,然后保留匹配数最多的。但是这个算法的复 杂度为边数的指数级函数。因此,需要寻求一种更 加高效的算法。 增广路的定义(也称增广轨或交错轨): 若P是图G中一条连通两个未匹配顶点的路径,并且 属M的边和不属M的边(即已匹配和待匹配的边)在P 上交替出现,则称P为相对于M的一条增广路径。
KM算法
穷举的效率-n!,我们需要更加优秀的算法。 定理: 设M是一个带权完全二分图G的一个完备匹配,给 每个顶点一个可行顶标(第i个x顶点的可行标用lx[i] 表示,第j个y顶点的可行标用ly[j]表示),如果对所 有的边(i,j) in G,都有lx[i]+ly[j]>=w[i,j]成立(w[i,j]表示 边的权),且对所有的边(i,j) in M,都有lx[i]+ly[j]=w[i,j] 成立,则M是图G的一个最佳匹配。证明很容易。

二分图(匈牙利,KM算法详解)

二分图(匈牙利,KM算法详解)
3,假如我们在1,2步过程中找到一条增广路, 那么修改各自 对应的匹配点,转步骤4,若无增广路, 则退出.
4,匹配数+1;
最小点覆盖
最小覆盖: 最小覆盖要求用最少的点(X集 合或Y集合的都行)让每条边都至少和其中一 个点关联。可以证明:最少的点(即覆盖数) =最大匹配数 M
简单的证明如下:
1
4
1
4
2
5 把图中红色线去掉
2
5
蓝色线加上
3
6
3
6
1
4
更改各自的匹配点
找到一个更好的匹配 2
5
3
6
总结
所以流程就是:
1,对于一个未匹配的节点u,寻找它的每条边,如果它的边上 的另一个节点v还没匹配则表明找到了一个匹配,直接转步 骤4;
2,假如节点u它边上的另一个节点v已经匹配,那么就转向跟 v匹配的节点,假设是w,然后再对w重复1,2的步骤,即寻找增 广路.
现在我们假设要求的是最大距离.那么就是求最大权 匹配. 下面我们先介绍一下KM算法
KM算法
基本概念:可行顶标和相等子图
可行顶标:L是一个关于结点的函数,L(x)是顶点x对应 的顶标值。可行顶标对于图中的每条边(x,y)都有 L(x)+L(y)>=w(x,y)
相等子图:只包含L(x)+L(y)=w(x,y)的边的子图
KM算法
定理:如果一个相等子图中包含完备匹配,那 么这个匹配就是最优匹配
证明:由于在算法过程一直保持顶标的可行性, 所以任意一个匹配的权值和肯定小于等于所有 结点的顶标之和,则相等子图中的完备匹配肯 定是最优匹配
KM算法
算法流程 设顶点Xi的顶标为a[i],顶点Yi的顶标为b[i] ⅰ.初始时,a[i]为与Xi相关联的边的最大权值,

求kM算法和匈牙利算法的程序代码

求kM算法和匈牙利算法的程序代码

求kM算法和匈牙利算法的程序代码kM算法和匈牙利算法的程序代码,最好是用matlab给出的,用c语言亦可。

不要用其他的编程语言。

//二分图最佳匹配,kuhn munkras算法,邻接阵形式,复杂度O(m*m*n)//返回最佳匹配值,传入二分图大小m,n和邻接阵mat,表示权值//match1,match2返回一个最佳匹配,未匹配顶点match值为-1//一定注意m<=n,否则循环无法终止//最小权匹配可将权值取相反数#include <string.h>#define MAXN 310#define inf 1000000000#define _clr(x) memset(x,0xff,sizeof(int)*n)int kuhn_munkras(int m,int n,int mat[][MAXN],int* match1,int* match2){ int s[MAXN],t[MAXN],l1[MAXN],l2[MAXN],p,q,ret=0,i,j,k;for (i=0;i<m;i++)for (l1[i]=-inf,j=0;j<n;j++)l1[i]=mat[i][j]>l1[i]?mat[i][j]:l1[i];for (i=0;i<n;l2[i++]=0);for (_clr(match1),_clr(match2),i=0;i<m;i++){for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for (k=s[p],j=0;j<n&&match1[i]<0;j++)if (l1[k]+l2[j]==mat[k][j]&&t[j]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}if (match1[i]<0){for (i--,p=inf,k=0;k<=q;k++)for (j=0;j<n;j++)if (t[j]<0&&l1[s[k]]+l2[j]-mat[s[k]][j]<p)p=l1[s[k]]+l2[j]-mat[s[k]][j];for (j=0;j<n;l2[j]+=t[j]<0?0:p,j++);for (k=0;k<=q;l1[s[k++]]-=p);}}for (i=0;i<m;i++)ret+=mat[i][match1[i]];return ret;}昨天帮一个同学完成了他的毕业论文上的指派问题的匈牙利算法程序。

最大匹配算法(匈牙利算法)

最大匹配算法(匈牙利算法)

最小路径覆盖
将n个点拆成2n个点,如1号变为1和1’, 1代表出边,1’代表进边。对于每个结点, 将与其相临的边连出来。 对已经连好的图求最大匹配数
最小路径覆盖
最小路径覆盖数=顶点数n-最大匹配数
Nkoj 1684 1465 1681 1070
courses Taxi Cab Scheme Girls and boys 信和信封的问题
一张残缺的棋盘,用1*2的矩形去覆盖它, 要求矩形不互相重叠棋盘染成黑白相间,黑色方格作为左 边的点,白色方格作为右边的点,相邻 的黑白方格中间连一条边。 对已经建好的图求最大匹配
二分图的最大独立数
最大独立数=最大匹配数
最小路径覆盖
一张图n个点,给定某些点之间可以用线 连起来。 问最少画多少笔才能将所有的点全部盖 住 poj1422
二分图的最小覆盖数
棋盘上有N个点,每次可以拿走一行或者 一列。 问最少多少次可以把棋盘上的所有点都 拿走
poj3041
二分图的最小覆盖数
将行作为左边的点,列作为右边的点, 原图中的每个点形成一条边,将代表其 行和列的点连接起来。 对已经建好的图求最大匹配
Konig定理
最大匹配数=最小覆盖数
二分图的最大独立数
二分图的 最大匹配
RCA
二分图
1
二分图是一种特殊的图 对于无向图G=(V,E),如 果V可以分为两个互不相 交的子集,并且图中的每 条边所依附的两点都属于 不同的子集,则图G则称 为一个二分图
1’ 2 2’ 3 3’ 4 4’ 5
最大匹配
给定一个二分图G,在G的一个子图的边 集中的任意两条边都不依附于同一个顶 点,则称此子图是一个匹配。 选择这样的边数最大的子集称为图的最 最 大匹配问题(maximal matching problem) 大匹配问题 如果一个匹配中,图中的每个顶点都和 图中某条边相关联,则称此匹配为完全 完全 匹配,也称作完备匹配。 完备匹配。 匹配 完备匹配

匈牙利算法——精选推荐

匈牙利算法——精选推荐

二分图最优匹配:对于二分图的每条边都有一个权(非负),要求一种完备匹配方案,使得所有匹配边的权和最大,记做最优完备匹配。

(特殊的,当所有边的权为1时,就是最大完备匹配问题)解二分图最优匹配问题可用穷举的方法,但穷举的效率=n!,所以我们需要更加优秀的算法。

先说一个定理:设M是一个带权完全二分图G的一个完备匹配,给每个顶点一个可行顶标(第i个x顶点的可行标用lx[i]表示,第j个y顶点的可行标用ly[j]表示),如果对所有的边(i,j) in G,都有lx[i]+ly[j]>=w[i,j]成立(w[i,j]表示边的权),且对所有的边(i,j) in M,都有lx[i]+ly[j]=w[i,j]成立,则M是图G的一个最优匹配。

Kuhn-Munkras算法(即KM算法)流程:v(1)初始化可行顶标的值v(2)用匈牙利算法寻找完备匹配v(3)若未找到完备匹配则修改可行顶标的值v(4)重复(2)(3)直到找到相等子图的完备匹配为止KM算法主要就是控制怎样修改可行顶标的策略使得最终可以达到一个完美匹配,首先任意设置可行顶标(如每个X节点的可行顶标设为它出发的所有弧的最大权,Y节点的可行顶标设为0),然后在相等子图中寻找增广路,找到增广路就沿着增广路增广。

而如果没有找到增广路呢,那么就考虑所有现在在匈牙利树中的X节点(记为S集合),所有现在在匈牙利树中的Y节点(记为T 集合),考察所有一段在S集合,一段在not T集合中的弧,取delta = min {l(xi)+l(yj)-w(xi,yj) , | xi in S, yj in not T} 。

明显的,当我们把所有S集合中的l(xi)减少delta之后,一定会有至少一条属于(S, not T)的边进入相等子图,进而可以继续扩展匈牙利树,为了保证原来属于(S,T )的边不退出相等子图,把所有在T 集合中的点的可行顶标增加delta。

随后匈牙利树继续扩展,如果新加入匈牙利树的Y节点是未盖点,那么找到增广路,否则把该节点的对应的X匹配点加入匈牙利树继续尝试增广。

匈牙利算法(二分图)

匈牙利算法(二分图)

匈⽛利算法(⼆分图)---------------------------------------------------------------------题材⼤多来⾃⽹络,本篇由神犇整理基本概念—⼆分图⼆分图:是图论中的⼀种特殊模型。

若能将⽆向图G=(V,E)的顶点V划分为两个交集为空的顶点集,并且任意边的两个端点都分属于两个集合,则称图G为⼀个为⼆分图。

匹配:⼀个匹配即⼀个包含若⼲条边的集合,且其中任意两条边没有公共端点。

如下图,图3的红边即为图2的⼀个匹配。

1 最⼤匹配在G的⼀个⼦图M中,M的边集中的任意两条边都不依附于同⼀个顶点,则称M是⼀个匹配。

选择这样的边数最⼤的⼦集称为图的最⼤匹配问题,最⼤匹配的边数称为最⼤匹配数.如果⼀个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。

如果在左右两边加上源汇点后,图G等价于⼀个⽹络流,最⼤匹配问题可以转为最⼤流的问题。

解决此问的匈⽛利算法的本质就是寻找最⼤流的增⼴路径。

上图中的最⼤匹配如下图红边所⽰:2 最优匹配最优匹配⼜称为带权最⼤匹配,是指在带有权值边的⼆分图中,求⼀个匹配使得匹配边上的权值和最⼤。

⼀般X和Y集合顶点个数相同,最优匹配也是⼀个完备匹配,即每个顶点都被匹配。

如果个数不相等,可以通过补点加0边实现转化。

⼀般使⽤KM算法解决该问题。

3 最⼩覆盖⼆分图的最⼩覆盖分为最⼩顶点覆盖和最⼩路径覆盖:①最⼩顶点覆盖是指最少的顶点数使得⼆分图G中的每条边都⾄少与其中⼀个点相关联,⼆分图的最⼩顶点覆盖数=⼆分图的最⼤匹配数;②最⼩路径覆盖也称为最⼩边覆盖,是指⽤尽量少的不相交简单路径覆盖⼆分图中的所有顶点。

⼆分图的最⼩路径覆盖数=|V|-⼆分图的最⼤匹配数;4 最⼤独⽴集最⼤独⽴集是指寻找⼀个点集,使得其中任意两点在图中⽆对应边。

对于⼀般图来说,最⼤独⽴集是⼀个NP完全问题,对于⼆分图来说最⼤独⽴集=|V|-⼆分图的最⼤匹配数。

K M 算 法 详 解 ( 2 0 2 0 )

K M 算 法 详 解 ( 2 0 2 0 )

【原创】我的KM算法详解0.二分图二分图的概念二分图又称作二部图,是图论中的一种特殊模型。

设G=(V, E)是一个无向图。

如果顶点集V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在X中,另一个在Y中,则称图G为二分图。

可以得到线上的driver与order之间的匹配关系既是一个二分图。

二分图的判定无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。

判断无向连通图是不是二分图,可以使用深度优先遍历算法(又名交叉染色法)。

下面着重介绍下交叉染色法的定义与原理首先任意取出一个顶点进行染色,和该节点相邻的点有三种情况:1.如果节点没有染过色,就染上与它相反的颜色,推入队列,2.如果节点染过色且相反,忽视掉,3.如果节点染过色且与父节点相同,证明不是二分图,return二分图博客推荐交叉染色法博客推荐:交叉染色法判断二分图另外附上二分图的性质博客:二分图的一些性质1.KM算法初步KM算法全称是Kuhn-Munkras,是这两个人在1957年提出的,有趣的是,匈牙利算法是在1965年提出的。

?增广路径增广路径定义:若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M 的一条增广路径(举例来说,有A、B集合,增广路由A中一个点通向B中一个点,再由B中这个点通向A中一个点……交替进行)增广路径有如下特性:?1. 有奇数条边?2. 起点在二分图的X边,终点在二分图的Y边?3. 路径上的点一定是一个在X边,一个在Y边,交错出现。

?4. 整条路径上没有重复的点?5. 起点和终点都是目前还没有配对的点,其他的点都已经出现在匹配子图中?6. 路径上的所有第奇数条边都是目前还没有进入目前的匹配子图的边,而所有第偶数条边都已经进入目前的匹配子图。

奇数边比偶数边多一条边?7. 于是当我们把所有第奇数条边都加到匹配子图并把条偶数条边都删除,匹配数增加了1.例如下图,蓝色的是当前的匹配子图,红色表示未匹配的路径,目前只有边x0y0,然后通过x1找到了增广路径:x1y0-y0x0-x0y2?增广路径有两种寻径方法,一个是深搜,一个是宽搜。

图论课件-匈牙利算法与最优匹配算法

图论课件-匈牙利算法与最优匹配算法

x4
x5
(2) NGl (S) y2, y3 T
y1 y2 y3
y4
y5
(3) 取:y2 NGl (S ) T
G l=(X, Y)
y2为饱和顶点,y2x1 ∈M,于是: S x1, x4,T y2
(2) NGl (S) y2, y3 T
(3) 取:y3 NGl (S ) T
y3为饱和顶点,y3x3 ∈M,于是:S x1, x3, x4,T y2, y3
11
1
0.5 n 0
0.5
1 2 1.5 t1
0.5
00
1 0.8
0.6 0.4 x 0.2
偶图中寻找最大匹配算法:
设M是G=(X, Y)的初始匹配。
(1) 置S=Φ, T=Φ;
(2) 若X-S已经M饱和,停止;否则,设u是X-S中的一 非饱和顶点,置S=S∪{u}。
(3) 若N(S)=T,转(5);否则,设y ∈N(S)-T。
y2
x5
x4
x2
y4
y3
u
扎根 u 的M交错树H
情形2 H包含除u外的M非饱和点。
y2
x4
x2
y4
y3
u
扎根 u 的M交错树H
4
1
0.5 n 0
0.5
1 2 1.5 t1
0.5
00
1 0.8
0.6 0.4 x 0.2
对于情形1,令S=V(H)∩X, T=V(H)∩Y,显然: T N(S)
1) 若N(S)=T, 由于S - {u}中点与T中点配对,所以有: |T|=|S|-1, 于是有: |N(S)| = |S|-1< |S|.由Hall定理,G中不存 在完美匹配;

K M 算 法 详 解

K M 算 法 详 解

KM算法详解(例题为HDU2255 带权二分图的最优匹配):希望你在阅读此篇博客时,你已经学会了匈牙利算法,这样会对你更有帮助哦!!!!!对于KM算法自己的通俗理解与代码详解:注:KM算法:就是在匈牙利基础上加了权值的束缚!那么,为了达到权值和最大,或者最小,就不能简单的去算最多的边数。

步骤:(以HDU2255 例题为例)1.首先要找到所有居民愿意花钱最多的那个房子。

题目中用到lx,ly数组,是为了同时调节两个数组,使得权值和最大。

或者说当要松弛的时候使得本来最大的矛盾权值和尽可能的损失小一些来得到满足条件的最大权值和!2.(lx[x]+ly[y]-w[x][y]=0)条件下进行匈牙利算法。

lx[x]+ly[y]-w[x][y]这个条件十分巧妙:(算法精髓)1.即可以只让指定居民找到它愿意付最多钱的房子。

2.又可以在发生多居民抢一个房子时,用它来得到该居民到其它房子的松弛量!(即该居民到其它房子比到这个用钱最多的房子愿意花的钱数上差的值。

)那么我们就要把发生矛盾的居民到其它房子的松弛量的最小值求出来。

再用它去松弛,就可以让原本矛盾的最大权值和,损失最小而得到满足条件的最大权值和对于每个居民有4个基本问题:1.这个房子访问过没有?2.这个房子能不能满足他的条件3.这个房子是否被别人住了4.被别人住了能不能得到调配代码如下:#include iostream#includecstdio#includecstringusing namespace std;#define MAX 310#define INF 125#define clr(x) memset(x,0,sizeof(x))int w[MAX][MAX];int lx[MAX],ly[MAX]; -***lx[i]初始化为A集合中 i 点能到B集合某一点的最大权值, ly[i] 初始化0;***-int link[MAX];int slack[MAX];int visx[MAX],visy[MAX];bool find(int x)visx[x]=1; -****得到发生矛盾的居民集合****-for(int y=1;y=n;y++) -**这个居民,每个房子都去试一试!(找到就退出)**-if(visy[y]) -****一个房子不需要重复访问****-continue;int t=lx[x]+ly[y]-w[x][y];-****按这个标准去用-匈牙利算法***- if(t==0) -**t==0标志这个房子可以给这位居民**-visy[y]=1;if(link[y]==0||find(link[y])) -****这房子没人住或可以让住这个房子的人去找另外的房子住****-link[y]=x;return true; -**那么就可以让这位居民住进来**-else if(slack[y]t) -**否则这个房子不能给这位居民!**-slack[y]=t; -***就要找到这个房子要松弛多少才能够给这位居民***--***且当有多个居民都对这个房子有松弛量时,要找到最小的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

图的匹配一、什么是图的匹配1.图的定义无向图:无向图G 是指非空有限集合V G ,和V G 中某些元素的无序对的集合E G ,构成的二元组(V G ,E G )。

V G 称为G 的顶点集,其中的元素称为G 的顶点。

E G 称为G 的边集,其中的元素称为G 的边。

在不混淆的情况下,有时记V =V G ,E =E G 。

如果V ={v 1,…,v n },那么E 中的元素e 与V 中某两个元素构成的无序对(v i ,v j )相对应,记e =v i v j ,或e =v j v i 。

在分析问题时,我们通常可以用小圆圈表示顶点,用小圆圈之的连线表示边。

二分图:设G 是一个图。

如果存在V G 的一个划分X ,Y ,使得G 的任何一条边的一个端点在X 中,另一个端点在Y 中,则称G 为二分图,记作G =(X ,Y ,E)。

如果G 中X 的每个顶点都与Y 的每个顶点相邻,则称G 为完全二分图。

2.匹配的相关概念设G =(V ,E)是一个图,E M ⊆,如果M 不含环且任意两边都不相邻,则称M 为G 的一个匹配。

G 中边数最多的匹配称为G 的最大匹配。

对于图G =(V ,E),在每条边e 上赋一个实数权w(e)。

设M 是G 的一个匹配。

定义∑∈=me e w M w )()(,并称之为匹配M 的权。

G 中权最大的匹配称为G 的最大权匹配。

如果对一切,e ∈E ,w(e)=1,则G 的最大权匹配就是G 的最大匹配。

设M 是图G=(V ,E)的一个匹配,v i ∈V 。

若v i 与M 中的边相关联,则称v i 是M 饱和点,否则称v i 为M 非饱和点。

如果G 中每个顶点都是M 饱和点,则称M 为G 的完美匹配。

设M 是G 的一个匹配,P 是G 的一条链。

如果P 的边交替地一条是M 中的边,一条不是M 中的边,则称P 为M 交错链。

类似地,我们可以定义G 的交错圈。

易知,G 的交错圈一定是偶圈。

一条连接两个不同的M 非饱和点的M 交错链称为M 增广链。

两个集合S 1与S 2的“异或”操作S 1⊕S 2是指集合S 1⊕S 2=(S 1∩S 2)\(S 1∪S 2) 容易看出,设M 是G 的匹配,P 是G 中的M 增广链、则M ⊕P 也是G 的匹配,而且1+=⊕M P M 。

图表 1 “异或”操作可以证明,G 中匹配M 是最大匹配当且仅当G 中没有M 增广链。

二、匹配算法1.二分图的最大匹配设有M个工人x1, x2, …, x m,和N项工作y1, y2, …, y n,规定每个工人至多做一项工作,而每项工作至多分配一名工人去做。

由于种种原因,每个工人只能胜任其中的一项或几项工作。

问应怎样分配才能使尽可能多的工人分配到他胜任的工作。

这个问题称为人员分配问题。

人员分配问题可以用图的语言来表述。

令X={x1, x2, …, x m},Y={y1, y2, …,y n},构造二分图G=(X, Y, E)如下:对于1≤i≤m,1≤j≤n,当且仅当工人xi 胜任工作yi时,G中有一条边xiyi,于是人员分配问题就成为在G中求一个最大匹配的问题。

求最大匹配常用匈牙利算法,它的基本思想是:对于已知的匹配M,从X中的任一选定的M非饱和点出发,用标号法寻找M增广链。

如果找到M增广链,则M就可以得到增广;否则从X中另一个M非饱和点出发,继续寻找M增广链。

重复这个过程直到G中不存在增广链结束,此时的匹配就是G的最大匹配。

这个算法通常称为匈牙利算法,因为这里介绍的寻找增广链的标号方法是由匈牙科学者Egerváry最早提出来的。

图表2 匈牙利算法理解了这个算法,就不难写出人员分配问题的解答了。

在给出程序之前,先做一些假设:为了简单起见,假设工人数等于工作数,即N=M,且N≤100,这里,N也可以看作是二分图的|X|和|Y|。

数据从文件input.txt中读入,首先是N和|E|,下面|E|行每行两个数(I, J),表示工人I 可以胜任工作J,即二分图中的边x i y j。

结果输出到文件output.txt,第一行是最大匹配数s,下面s行每行两个数(I, J),表示分配工人I做工作J,即匹配边x i y j。

下面是人员分配问题的参考解答,该算法的时间复杂度为O(n3)。

Program match;constmaxn = 100;varmap: array[1 .. maxn, 1 .. maxn] of boolean; {保存二分图} cover: array[1 .. maxn] of boolean; {标记一个点是否为饱和点} link: array[1 .. maxn] of integer; {保存匹配边}n: integer; {顶点数}procedure init; {读入}vari, e, x, y: integer;beginassign(input, 'input.txt'); reset(input);readln(n, e);for i := 1 to e do beginreadln(x, y); map[x, y] := true;end;close(input);end;function find(i: integer): boolean; {从i出发,找增广链}vark, q: integer;beginfind := true;for k := 1 to n doif map[i, k] and not cover[k] then beginq := link[k]; link[k] := i; cover[k] := true;if (q = 0) or find(q) then exit;link[k] := q;end;find := false;end;procedure main; {求匹配}vari: integer;beginfor i := 1 to n do beginfillchar(cover, sizeof(cover), 0);find(i);end;end;procedure print; {输出}vari, s: integer; beginassign(output, 'output.txt'); rewrite(output);s := 0; for i := 1 to n do if link[i] <> 0 then s := s + 1; writeln(s);for i := 1 to n do if link[i] <> 0 then writeln(link[i], ' ', i); close(output); end;begin init; main; print; end.2.二分图的最大权匹配对于上面的人员分配问题,如果还考虑到工人做工的效率,就可以提出所谓的分派问题:应该怎样分配才能使总的效率最大?同上一节,我们可以构造一个二分图G ,如果把工人x i 做工作y i 的效率w ij 看作是G 中边x i y i 的权,则分派问题就相当于在赋权二分图G 中求一个最大全匹配。

由线性规划的知识,求二分图G 的最大权匹配,只需在匈牙利算法的基础上少许改进即可。

它的基本思想是,对二分图的顶点编号,然后根据编号构造一个新的二分图G ’,最后把求G 的最大权匹配转换为求G ’的完美匹配。

下面的这条定理是这个算法的理论基础。

定理:设M 是赋权图(权非负)的完全二分图),,,(w E Y X G =的一个完美匹配,这里Y X =。

如果存在一组},{j i μλ,满足),,2,1,(,n j i w ij j i =≥+μλ,并且对一切M y x j i ∈,均有ij j i w =+μλ,则M 是G 的最大权匹配。

下面,给出求最大权匹配的程序。

输入文件中首先是N 和|E|,下面|E|行每行三个数(I, J, W),表示工人I 做工作J 的效率是W 。

程序输出包括每个工人的选择和最后的总效益。

其它假设参见上一节的算法假设。

这个算法的时间复杂度也是O(n 3)。

Program maxmatch; constmaxn = 100; varmap: array[1 .. maxn, 1 .. maxn] of integer; {保存二分图}link, lx, ly: array[1 .. maxn] of integer; {保存匹配边和每个点的标号} x, y: array[1 .. maxn] of boolean; {标记一个点是否为饱和点} n: integer; {顶点数}procedure init; {读入} vari, e, x, y: integer; beginassign(input, 'input.txt'); reset(input);for i := 1 to e do readln(x, y, map[x, y]);close(input);end;function find(v: integer): boolean; {从v出发,找增广链} vari, k: integer;beginfind := true;x[v] := true;for i := 1 to n doif not y[i] and (lx[v] + ly[i] = map[v, i]) then beginy[i] := true; k := link[i]; link[i] := v;if (k = 0) or find(k) then exit;link[i] := k;end;find := false;end;procedure main; {求最大权匹配}vari, j, k, d: integer;beginfillchar(lx, sizeof(lx), 0); fillchar(ly, sizeof(ly), 0);for i := 1 to n dofor j := 1 to n doif map[i, j] > lx[i] then lx[i] := map[i, j];for k := 1 to n dorepeatfillchar(x, sizeof(x), 0); fillchar(y, sizeof(y), 0);if find(k) then break;d := maxint;for i := 1 to n do if x[i] thenfor j := 1 to n do if not y[j] thenif lx[i] + ly[j] - map[i, j] < d thend := lx[i] + ly[j] - map[i, j];for i := 1 to n do if x[i] then lx[i] := lx[i] - d;for i := 1 to n do if y[i] then ly[i] := ly[i] + d;until false;end;procedure print; {输出}vari, s: integer;beginassign(output, 'output.txt'); rewrite(output);s := 0;for i := 1 to n do s := s + map[link[i], i];close(output);end;begininit;main;print;end.3. 任意图的匹配任意图的最大匹配算法也是建立在找增广链的基础上的,只是任意图的增广链要比二分图难找得多。

相关文档
最新文档