匈牙利算法

二分图的最大匹配可以转换为一个网络流的问题,但是我们一般使用匈牙利算法,这种算法更易于理解,方便编写。
介绍这个算法之前,首先要介绍一些必要的概念。

交错路 : 从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边,这样交替下去,这条路径称为交错路。

增广路 : 从一个未匹配点出发,依次遍历未匹配边、匹配边、未匹配边,这样交替下去,如果最后一个点是未匹配点,这条路径称为增广路。换句话说,起点和终点都为未匹配点的交错路为增广路(特别提醒,这里的增广路和网络流中的增广路的意义不同)


如图所示,图6 是图5 的其中一条增广路,可以看出由未匹配点9出发,依次沿着边edge(9,4)−>edge(4,8)−>edge(8,1)−>edge(1,6)−>edge(6,2)e d g e ( 9 , 4 ) −> e d g e ( 4 , 8 ) −> e d g e ( 8 , 1 ) −> e d g e ( 1 , 6 ) −> e d g e ( 6 , 2 )edge(9,4)−>edge(4,8)−>edge(8,1)−>edge(1,6)−>edge(6,2) 到达未匹配点2,显然,这是一条增广路。

观察图6我们可发现增广路的一些特点。

  1. 增广路一定有奇数条边。

  2. 增广路中未匹配边一定比匹配边多一条(因为是从未匹配点出发走交错路到未匹配点结束)

这里其实就表明了研究增广路的意义。
如果找到了一条增广路,那么将未匹配点与匹配边的身份调换,那么匹配的边数就多了一条,这样直到找不到增广路为止,那么整个图的匹配的边数一定最大,也就是找到了二分图的最大匹配。

这里的身份调换是指 :
原来匹配的边为edge(1,6), edge (4,8),匹配边数为2 。找到一条增广路(这里不一定从9开始找,任何一个未匹配点都可以)后,现在匹配的边为edge(2,6), edge(1,8), edge(4,9), 匹配边数为3。

匈牙利算法正是利用了增广路的这个性质,从X集合中找到一个未匹配点,寻找增广路,找到了匹配数+1,如果没有找到,那么从X中找到下一个未匹配的点,再次寻找增广路…重复上述过程,直到X集合中的所有节点都被“增广”完毕,无论如何都找不到增广路,那么整个图的匹配数就最大了

伪代码:

void hungary()//匈牙利算法
{for i->1 to nx//对于集合X中的每一个节点if (从未匹配点i出发有增广路)匹配数++;输出 匹配数;
}
bool findpath(x)//寻找从x出发的对应项出的可增广路
{//crossPath[x] = true;这条语句可能会有很多人加上,但是实际上crossPtah总是记录集合Y中的节点是否在交错路上for each edge(x,y) in G.E{if(y is not in crossPath){add y into crossPathlastX = match[y];//lastX是X集合的上一个与y匹配的节点if(y is not matched or findpath(lastX))//如果y已经被了,那么试试从lastX能不能另外找到一条增广路,把当前增广路让给现在的x{match[y] = x;//match[x] = y,wrong !return true;//从x出发有增广路}}}return false;//从x出发没有增广路
}

KM算法

如果二分图的每条边都有一个权重,要求一种完备匹配方案,使得所有匹配边的权重和最大,记作最佳完美匹配。一般使用KM算法解决该问题

KM算法,是对匈牙利算法的一种贪心扩展。

流程

Kuhn-Munkras算法(即KM算法)流程:

  1. 初始化可行顶标的值 (设定lx,ly的初始值)
  2. 用匈牙利算法寻找相等子图的完备匹配
  3. 若未找到增广路则修改可行顶标的值
  4. 重复(2)(3)直到找到相等子图的完备匹配为止

KM算法的核心部分即控制修改可行顶标的策略使得最终可到达一个完美匹配

伪代码:

bool findpath(x)
{visx[x] = true;for(int y = 1 ; y <= ny ; ++y){if(!visy[y] && lx[x] + ly[y] == weight(x,y)) //y不在交错路中且edge(x,y)必须在相等子图中{visy[y] = true;if(match[y] == -1 || findpath(match[y]))//如果y还为匹配或者从y的match还能另外找到一条匹配边{match[y] = x;return true;}}}return false;
}
void KM()
{for(int x = 1 ; x <= nx ; ++x){while(true){memset(visx,false,sizeof(visx));//访问过X中的标记memset(visy,false,sizeof(visy));//访问过Y中的标记if(findpath(x))//找到了增广路,跳出继续寻找下一个break;else{for(int i = 1 ; i <= nx ; ++i){if(visx[i])//i在交错路中{for(int j = 1 ; j <= ny ; ++j){if(visy[j])//j不在交错路中,对应第二类边delta = Min(delta,lx[x] + ly[y] - weight(i,j))}}}for(int i = 1 ; i <= nx ; ++i)//增广路中xi - deltaif(visx[i])lx[i] -= delta;for(int j = 1 ; j <= ny ; ++j)//增广路中yj + deltaif(visy[j])ly[j] += delta;}}
}

参考链接:
https://blog.csdn.net/sixdaycoder/article/details/47680831
https://blog.csdn.net/sixdaycoder/article/details/47720471

匈牙利算法和KM算法的理解相关推荐

  1. 多目标跟踪算法中之图匹配——匈牙利算法和KM算法详解

    目录 一.匈牙利算法 1.算法背景及思想 2.最大匹配 3.最优匹配/完美匹配 4.增广路径 5.代码实现 6.匈牙利算法总结 6.1.深度优先 6.2. 广度优先 二.KM算法思想及局限性 代码示例 ...

  2. 匈牙利算法和hopcroft_karp算法模板

    今晚学习了hopcroft_karp算法,留个模板,顺便也留个匈牙利算法模板. 题目为POJ 1469,在本题中,两种算法所用时间基本一致 //hopcroft_karp算法,复杂度O(sqrt(n) ...

  3. BF算法和KMP算法

    给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配(string matching,也称模式匹配),T称为模式.这里将介绍处理串匹配问题的两种算法,BF算法和KMP算法. BF算法 (暴力匹配 ...

  4. 操作系统之存储管理——FIFO算法和LRU算法

    操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...

  5. 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)

    图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...

  6. DP之Warshall算法和Floyd算法

    DP之Warshall算法和Floyd算法 上2篇详细分析了动态规划的一些理解,传统的教材上就大概说了下空间换时间,记忆以避免重复计算等. 然后我们在文章中深入的分析和解释了交叠子问题是怎么表现的,最 ...

  7. 浅谈迪杰斯特拉(Dijkstra)算法和A*算法原理及实现

    写在前面 最近我在学习一门名叫<智能自主机器人及系统>的课程,虽然跟过去所学的<机器人学>在部分内容上有所重复,但该课程的应用性更强.对于不同的机器人,如差速轮式车.四轮车.四 ...

  8. Widar2.0:SAGE算法和SAGE算法在在无线信道参数估计中的应用

    Widar2.0:SAGE算法和SAGE算法在在无线信道参数估计中的应用 C1 本文背景 C2 SAGE算法 C2.1 EM算法 C2.2 SAGE算法 C2.3 SAGE算法和SAGE算法在在无线信 ...

  9. 链接挖掘算法之PageRank算法和HITS算法

    参考资料:http://blog.csdn.net/hguisu/article/details/7996185 更多数据挖掘算法:https://github.com/linyiqun/DataMi ...

  10. 加权无向图与最小生成树(Prim算法和Kruskal算法)

    目录 0 引入 1 图的最小生成树定义及相关约定 2 最小生成树原理 2.1 性质 2.2 切分定理 3 贪心思想 4 Prim算法 4.1 算法步骤 4.2 API设计 4.3 Java代码演示 5 ...

最新文章

  1. 流量调整和限流技术 【转载】
  2. Nginx自定义模块编写:根据post参数路由到不同服务器
  3. ListT中,Remove和RemoveAt区别
  4. 虚拟机下Linux安装图解之四:VMware Tools 的安装
  5. ACE_Proactor网络通信示例
  6. Xmind settings lower
  7. Android Studio 如何导入第三方jar包(整理)
  8. java中常量final的用法_详解Java中final的用法
  9. php 邮件类库,[3.3]-扩展类库:基于PHPMailer的邮件发送 | PhalApi(π框架) - PHP轻量级开源接口框架 - 接口,从简单开始!...
  10. Oracle 已命名的异常
  11. 硬盘安装Windows需要了解的DOS命令
  12. BZOJ3495 : PA2010 Riddle
  13. excel 对列数据进行去重操作
  14. qq文件未上传至平台服务器,QQ传送离线文件慢是什么原因?原因及处理方法
  15. c语言vt指令,VT系列一:VT简述
  16. 《Sass 基础教程》共40节宁皓网课程
  17. 视频类APP体验报告
  18. TapTap 算法平台的 Serverless 探索之路
  19. 逆变器阻抗扫描 扫频法 阻抗扫描 阻抗建模验证
  20. s盒c语言算法,AES加密算法中的S盒及其C语言实现

热门文章

  1. 帧数达不到144用144hz_专业FPS玩家讲解:60Hz与144Hz刷新率的问题
  2. 绿竹生物冲刺港股:年期内亏损超5亿 泰格医药与北京亦庄是股东
  3. 关于CWMP基础(三)----(TR111)DHCP
  4. c# AD域 权限管理
  5. SQL SERVER 2012/2014 序列号密钥
  6. ios mysql工具_iOS数据库可视化工具--直接在iPhone操作你的数据库
  7. js如何实现页面跳转(大全)
  8. app页面html制作工具,app页面设计制作软件(最好用的6款设计软件)
  9. 光环PMP 三模模拟题
  10. html实例,实现表单