KM算法的正确性基于以下定理:

若由二分图中所有满足A[i]+B[i]=w[i][j]的边C(i,j)构成的子图(即相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配

基本概念

1.完备匹配

设G=<V1,V2,E>为二分图,|V1|<=|V2|,M为G中的一个最大匹配,且|M|=V1,则称M为V1到V2的完备匹配。

通俗的理解,就是把V1中所有的点都匹配完

2.可行顶标

对于左边的点设为LX[maxn]数组,右边的点设为LY[maxn]数组,w[i][j]表示 v[i] 到 v[j] 的权值

3.相等子图

相等子图为完备匹配中所有的匹配,即全部V1中的点和与V1中的点匹配的V2中的点,但是边只包含 LX[i]+LY[j]=W[i][j]的边

4.最优完备匹配

最优完备匹配就是在完备匹配的条件下求解权值最大或者最小,若由二分图中所有满足A[i]+B[i]=W[i][j]的边C(i,j)构成的相等子图有完备匹配,那么这个完备匹配就是二分图的最大权匹配

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

5.交错树

对V1中的一个顶点进行匹配的时候,所标记过的V1,V2中的点以及连线,形成一个树状的图

KM算法原理

1.基本原理

该算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题。
设顶点V1的顶标lx[i],V2顶点的顶标为LY[j],顶点V1的i与V2的j之间的边权为V(i,j)。在算法执行的过程中,对于任一条边C(i,j),LX[i]+LY[i]>=V[i,j]始终成立

2.基本流程

(1)初始化时为了使 LX[i] + LY[j] >= V [i,j]恒成立,将V1的点的标号记为与其相连的最大边权值,V2的点标号记为0
(2)用匈牙利算法在相等子图寻找完备匹配
(3)若未找到完备匹配,则修改可行顶标的值,扩充相等子图
(4)重复(2)(3)直到找到相等子图的完备匹配为止

3.这里值得注意的是找完备匹配不难理解,主要是进行可行顶标的修改扩充相等子图

引用:

朴素的实现方法:时间复杂度为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值即可。但还要注意一点:修改 顶标后,要把所有的slack值都减去d。

引用:

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

我们求当前相等子图的完备匹配失败了,是因为对于某个V1顶点,我们找不到一条从它出发的交错路。这时我们获得了一棵交错树,它的叶子结点全部是V1顶点。现在我们把交错树中V1顶点的顶标全都减小某个值d,V2顶点的顶标全都增加同一个值d,那么我们会发现:

1)两端都在交错树中的边(i,j),lx[ i ]+ly[j]的值没有变化。也就是说,它原来属于相等子图,现在仍属于相等子图。

2)两端都不在交错树中的边(i,j),lx[ i ]和ly[j]都没有变化。也就是说,它原来属于(或不属于)相等子图,现在仍属于(或不属于)相等子图。

3)V1端不在交错树中,V2端在交错树中的边(i,j),它的lx[ i ]+ly[j]的值有所增大。它原来不属于相等子图,现在仍不属于相等子图。

4)V1端在交错树中,V2端不在交错树中的边(i,j),它的lx[ i ]+ly[j]的值有所减小。也就说,它原来不属于相等子图,现在可能进入了相等子图,因而使相等子图得到了扩大。

//HDU2255
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 310
#define INF 0x3f3f3f3f
#define clr(x)  memset(x,0,sizeof(x))
int w[maxn][maxn];//w[i][j]表示i到j的权值
int lx[maxn],ly[maxn];//同时调节两个数组,使得权值和最大
int n;
//n1,n2为二分图的顶点集,其中x属于n1,y属于n2
//link记录n2中的点y在n1中所匹配的x点的编号
int link[maxn];
int slack[maxn];//松弛操作
int visx[maxn],visy[maxn];
bool dfs(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)//标志这个房子可以给这个居民{visy[y]=1;
//这个房子没人住或者可以让住着个房子的人去找另外的房子住if(link[y]==0||dfs(link[y])){link[y]=x;return 1;//可以让这位居民住进来}}else if(slack[y]>t)//否则这个房子不能给这位居民slack[y]=t;}return 0;
}
int KM()
{clr(lx);clr(ly);clr(link);//首先把每个居民出的钱最多的那个房子给他for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(lx[i]<w[i][j])lx[i]=w[i][j];//在满足上述条件之后,给第i位居民分配房子for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)slack[j]=INF;//松弛量while(1)//直到给这个居民找到房子为止{clr(visx);clr(visy);if(dfs(i))  break;//找到房子,就跳出循环int d=INF;for(int k=1;k<=n;k++)if(!visy[k]&&d>slack[k])d=slack[k];//找到最小松弛量for(int k=1;k<=n;k++)//松弛操作,使发生矛盾的居民有更多选择{if(visx[k]) lx[k]-=d;//将矛盾居民的要求降低,使发生矛盾的居民有更多if(visy[k]) ly[k]+=d;//使发生矛盾的房子在下一个子图,保持矛盾}}}int ans=0;for(int i=1;i<=n;i++)ans+=w[link[i]][i];return ans;
}
int main()
{while(~scanf("%d",&n)){clr(w);//每个案例都重置为0for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&w[i][j]);//输入每条边的权值printf("%d\n",KM());}return 0;
}

二分图最大权匹配 KM算法相关推荐

  1. 【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))

    整理的算法模板合集: ACM模板 匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 . 考虑到二分图中两个集合中的点并不总是相同,为了能应用 ...

  2. 二分图最佳完美匹配——KM算法总结

    KM 算法 求解二分图最佳完美匹配的算法. 先来看一道例题Hdu 2255. 显然是KM的裸题.假设我们要匹配集合X和Y的点,先给每个点一个顶标Lx和Ly. 为什么要给顶标? 首先顶标是我们限制边的一 ...

  3. 二分图的完全匹配---KM算法

    写在之前:更多二分图知识,请关注--->二分图知识导航篇 引述 KM算法全称Kuhn-Munkres,是一种求二分图完全.完美.最佳等匹配的方法,其实三个形容词都是指两个集内的所有顶点能够一一匹 ...

  4. 二分图最佳完美匹配——KM算法

    前情概要 学km算法之前,笔者还是希望大家已经掌握了匈牙利算法--也就是对于求解二分图最大匹配的算法.学习本算法的前提除了已经掌握C++语言之外,还需要掌握邻接表存图法,不会的朋友这里有传送门 [微笑 ...

  5. HDU - 2255 奔小康赚大钱(二分图最大权匹配+KM)

    题目链接:点击查看 题目大意:中文题目,简单来说就是n个人和n个房子最大匹配,需要一一对应并且满足权值和最大 题目分析:二分图的完备匹配,条件完全符合KM算法的局限性,直接套模板即可,后续学习费用流( ...

  6. HDU 1853 HDU 3488【有向环最小权值覆盖问题 】带权二分图匹配 KM算法

    HDU 1853 & HDU 3488[有向环最小权值覆盖问题 ]最小费用最大流 In the kingdom of Henryy, there are N (2 <= N <= ...

  7. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  8. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  9. 二分图最大权匹配问题KM算法讲解 HDU 2255 奔小康赚大钱

    作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...

最新文章

  1. 微软:97%电子邮件属于垃圾邮件
  2. 服务器被修改,我的世界
  3. 这老哥把GPU当暖气用,省钱了
  4. python自动化办公入门书籍推荐-好书推荐 | Python 如此神奇,让繁琐工作自动化...
  5. 从Google PR值审定标准来学习如何做推广
  6. Ubuntu开启NFS、SSH服务(驱动开发用到、电脑端登录ARM板用到)
  7. 心想技术驱动业务,却在背道而驰
  8. MacOS 的 Automator 实用案例详解
  9. 主机关机后第二天就无法开机_iphone没电自动关机后无法充电和开机的解决办法!(亲身经历)...
  10. charles抓包工具使用指南
  11. java控制台输出等腰三角形,并且是倒序正序输出【原创】
  12. “现有人工智能都是二流的”
  13. android 首页接口设计方案,Android开发最佳实践——1.接口设计
  14. django - 修改 自增长id,起始值
  15. 课程设计之贪吃蛇小游戏制造
  16. python 3d绘图模块_在Python 3中绘制3D多边形
  17. 怎么用单片机做一个比较有创新的东西?
  18. 游戏开发中为什么要控制模型的面数
  19. 一站式轻监控轻运维系统nezha(上篇)
  20. matlab从mp4文件中提取音频,怎么提取MP4视频中的音频,将MP4格式转换为MP3格式

热门文章

  1. 217. Contains Duplicate数组重复元素 123
  2. 腾讯云+校园扶持计划是bug还是福利
  3. matlab新手入门(四)(翻译)
  4. case的执行顺序 嵌套使用
  5. 用于正则表达式的 Regex.Matches静态方法的几种用法
  6. Spring vs Seam
  7. ASP.NET中的状态管理
  8. sql长整型_SQL性能优化,太太太太太太太有用了!
  9. 10通信端口感叹号_S71200 技术篇——MODBUS TCP通信
  10. mysql 批量修改数据库存储引擎_mysql批量修改表存储引擎