在看这篇博文之前建议看一下上一篇匈牙利法解决二分图最大匹配问题:

  https://www.cnblogs.com/fangxiaoqi/p/10808729.html

  这篇博文参考自:https://www.cnblogs.com/logosG/p/logos.html

最优匹配

  我们这里先说一下什么叫做最优匹配(也被称作最大带权分配)。

  简而言之,最优匹配就是指在带权边的二分图中,求一个匹配使得匹配边上的权值和最大。

  

两个例子

例子1

  出自wenr博客: http://www.cnblogs.com/wenruo/p/5264235.html

  这也是一个拯救单身的例子。红线上的权值表示女生对男生的好感度,至于单身男青年,对于女生的期望为0(有妹子就行,不挑),最优权值匹配即好感度之和最大。

  

  一:将女生的最大期望和男生的期望标出来,开始匹配。

  

  ==========================女1==========================

  女1 X 男1 : 4 + 0 != 3  不匹配;

  女1 X 男2:  4 + 0  = 4  匹配;

  成功脱单。

  ==========================女2==========================

  女2 X 男1: 3 + 0 != 2 不匹配;

  女2 X 男2: 3 + 0 != 1 不匹配;

  女2 X 男3: 3 + 0  = 3  匹配;

  但是!男3 已经 名草有主了。

  这时,男3 是个香饽饽,妹纸们都抢着要。男3对女生的期望 +1 ,而为了更好的分配,抢男生的妹子们要对男生的要求要降低一点

  局势就变成这样了:

  

  二:接下来就是一个递归的过程喽(下面的也是)

  ==========================女2==========================

  女2 X 男1: 2 + 0 != 2  匹配;

  成功脱单。

  ==========================女3==========================

  女3 X 男3: 5 + 1 != 5  不匹配;

  然后妹子3只能降低标准了。

  

  ==========================女3==========================

  女3 X 男3: 4 + 1 != 5  匹配;

  但是!男3有了吖。好叭,男3再次增加期望(渣男),妹子3和妹子1把要求降低一点。

  妹子1尝试换人,去和妹子2抢男1。

  但是!男1也有了吖。好叭,男1的期望+1,妹子2的期望降低一点。

  妹子2尝试换人,去和男2匹配。

  成功脱单。

  

  最后,女1 X 男1,女2 X 男2,女3 X 男3 为最优匹配,大团圆结局。

  而对于这种问题我们为什么要用KM算法?这显然是可以看出来的。但是,当单身男女数量越来越多,很难直接看出,而且如果仅仅用匈牙利算法找最大匹配然后比较每个最大匹配的权值来找最优匹配的实行难度也就越来越大,使用KM算法是一种好的选择。从上面的例子我们可以看出,KM算法是基于匈牙利方法进行不断进行递归和贪心的。

例子2

  出自 https://www.cnblogs.com/logosG/p/logos.html

  这是一个公司任免问题。

  在一家公司里,有员工A,B,C,有三种工作a,b,c,如果员工和工作之间有线相连,则代表员工能胜任这份工作,而每个员工做每份工作的效率各不相同,图中的权值代表工作效率,而我们的目的就是做合适的安排保证最大的效率。

  

  标出最大权值和右侧的期望。

  

  ==========================安排A==========================

  A--a: 4 + 0 != 3  不匹配;

  A--c: 4 + 0  = 4     匹配;

  ==========================安排B==========================

  B--a: 3 + 0 != 2  不匹配;

  B--b: 3 + 0 != 1  不匹配;

  B--c: 3 + 0 != 3     匹配;但是产生冲突。

  进行 -1 和 +1 的操作,来波递归。

  

  B--a: 2 + 0 = 2   匹配。

  ==========================安排C==========================

  C--c: 5 + 1 != 5   不匹配;  对C减1

  

  C--c: 4 + 1 = 5   匹配但冲突;(情形类似于例1,递归和贪心即可)

  最终,A--a,B--b,C--c。  

KM算法的思想

  KM算法是对匈牙利算法的一种贪心扩展,而其思想是通过给每个顶点一个标号(叫做顶标)来把求完备匹配(匈牙利算法求出完备匹配)下的最大权匹配问题(即最优分配)。通过修改某些点的符号(但要满足点标始终是可行的),不断增加图中可行边总数,直到图中存在仅由可行边组成的完全匹配为止,此时这个匹配一定是最佳的。

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

KM算法的步骤

  1. 用邻接矩阵(或其他方法也行啦)来储存图,注意:如果只是想求最大权值匹配而不要求是完全匹配的话,请把各个不相连的边的权值设置为0。
  2. 运用贪心算法初始化标杆。
  3. 运用匈牙利算法找到完备匹配。
  4. 如果找不到,则通过修改标杆,增加一些边。
  5. 重复3,4的步骤,直到完全匹配时可结束。

KM算法的流程

  (1)初始化可行顶标的值 (设定$lx$,$ly$的初始值) 。

  (2)用匈牙利算法寻找相等子图的完备匹配。  

  (3)若未找到增广路则修改可行顶标的值。

  重复(2)(3)直到找到相等子图的完备匹配为止。

参考自:http://www.cnblogs.com/zpfbuaa/p/7218607.html

hdoj 2255 奔小康赚大钱

  我们以HDOJ2255为例。http://acm.hdu.edu.cn/showproblem.php?pid=2255

奔小康赚大钱

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15718    Accepted Submission(s): 6746

  Problem Description
  传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
  这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
  另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱。由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内给出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万(当然是在他们的经济范围内)。.现在这个问题就是村领导怎样分配房子才能使收入最大(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的)?

  Input

  输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第 i 个村民对第 j 间房出的价格(n<=300)。
  Output
  请对每组数据输出最大的收入值,每组的输出占一行。
  Sample Input
  2
  100 10
  15 23
  Sample Output
  123
  水题一道,直接套模板即可。
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int INF = 0x3f3f3f3f;
  4.  
  5. int love[][]; // 每个妹子对每个男生的好感度
  6. int ex_girl[]; // 每个妹子的期望值
  7. int ex_boy[]; // 每个男生的期望值
  8. bool vis_girl[]; // 每一轮匹配匹配过的女生
  9. bool vis_boy[]; // 每一轮匹配匹配过的男生
  10. int match[]; // 每个男生匹配到的妹子 如果没有则为-1
  11. int slack[]; // 每个汉子如果能被妹子倾心最少还需要多少期望值
  12. int n;
  13.  
  14. bool dfs(int girl){
  15. vis_girl[girl] = true;
  16. for (int boy = ; boy < n; boy++) {
  17. if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
  18. int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
  19. if (gap == ) { // 如果符合要求
  20. vis_boy[boy] = true;
  21. if (match[boy] == - || dfs( match[boy] )) { // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
  22. match[boy] = girl;
  23. return true;
  24. }
  25. }else{
  26. slack[boy] = min(slack[boy], gap); // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子
  27. }
  28. }
  29. return false;
  30. }
  31. int KM(){
  32. memset(match, -, sizeof match); // 初始每个男生都没有匹配的女生
  33. memset(ex_boy, , sizeof ex_boy); // 初始每个男生的期望值为0
  34. // 每个女生的初始期望值是与她相连的男生最大的好感度
  35. for (int i = ; i < n; i++) {
  36. ex_girl[i] = love[i][];
  37. for (int j = ; j < n; j++) {
  38. ex_girl[i] = max(ex_girl[i], love[i][j]);
  39. }
  40. }
  41. // 尝试为每一个女生解决归宿问题
  42. for (int i = ; i < n; i++) {
  43. fill(slack, slack + n, INF); // 因为要取最小值 初始化为无穷大
  44. while(){
  45. // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
  46. // 记录每轮匹配中男生女生是否被尝试匹配过
  47. memset(vis_girl, false, sizeof vis_girl);
  48. memset(vis_boy, false, sizeof vis_boy);
  49. if(dfs(i)) break; // 找到归宿 退出
  50. // 如果不能找到 就降低期望值
  51. // 最小可降低的期望值
  52. int d = INF;
  53. for (int j = ; j < n; j++)
  54. if (!vis_boy[j]) d = min(d, slack[j]);
  55. for (int j = ; j < n; j++) {
  56. // 所有访问过的女生降低期望值
  57. if (vis_girl[j]) ex_girl[j] -= d;
  58. // 所有访问过的男生增加期望值
  59. if (vis_boy[j]) ex_boy[j] += d;
  60. // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
  61. else slack[j] -= d;
  62. }
  63. }
  64. }
  65. // 匹配完成 求出所有配对的好感度的和
  66. int res = ;
  67. for (int i = ; i < n; i++)
  68. res += love[match[i]][i];
  69. return res;
  70. }
  71. int main(){
  72. while (cin>>n) {
  73. for (int i = ; i < n; i++)
  74. for (int j = ; j < n; j++)
  75. cin>>love[i][j];
  76. cout<<KM()<<endl;
  77. }
  78. return ;
  79. }
 
 

Kuhn-Munkras算法解决二分图最优权值匹配的更多相关文章

  1. POJ 2195 Going Home 【二分图最小权值匹配】

    传送门:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  2. POJ-2195 Going Home---KM算法求最小权值匹配(存负边)

    题目链接: https://vjudge.net/problem/POJ-2195 题目大意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致.man每移动一格 ...

  3. POJ 3565 Ants 【最小权值匹配应用】

    传送门:http://poj.org/problem?id=3565 Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: ...

  4. 「日常温习」Hungary算法解决二分图相关问题

    前言 二分图的重点在于建模.以下的题目大家可以清晰的看出来这一点.代码相似度很高,但是思路基本上是各不相同. 题目 HDU 1179 Ollivanders: Makers of Fine Wands ...

  5. 【uva 1349】Optimal Bus Route Design(图论--网络流 二分图的最小权完美匹配)

    题意:有一个N个点的有向带权图,要求找若干个有向圈,使得每个点恰好属于一个圈.请输出满足以上条件的最小权和. 解法:有向圈?也就是每个点有唯一的后继.这是一个可逆命题,同样地,只要每个点都有唯一的后继 ...

  6. hdu1533 Going Home km算法解决最小权完美匹配

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  7. POJ 2125 Destroying The Graph 二分图 最小点权覆盖

    POJ2125 题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值.问最小权值和的解决方案,要输出操作. ...

  8. ZOJ-2342 Roads 二分图最小权值覆盖

    题意:给定N个点,M条边,M >= N-1.已知M条边都有一个权值,已知前N-1边能构成一颗N个节点生成树,现问通过修改这些边的权值使得最小生成树为前N条边的最小改动总和为多少? 分析:由于计算 ...

  9. Dijkstra算法解决单源最短路径

    单源最短路径问题:给定一个带权有向图 G = (V, E), 其中每条边的权是一个实数.另外,还给定 V 中的一个顶点,称为源.现在要计算从源到其他所有各顶点的最短路径长度.这里的长度是指路上各边权之 ...

随机推荐

  1. Android Studio +git+jenkins+gitHub

    之前做的jenkins+gitlab的jmeter,,,其实已经记不太清楚了. 最近又在搞Android学习,就试一下AndroidStudio+jenkins自动打包apk看看. step1: An ...

  2. 谷歌浏览器(Google Chrome)开发调试详细介绍

    很多Web前台开发者都喜欢这种浏览器自带的开发者工具,这对前台设计.代码调试很大帮助的. Chrome浏览器得益于其优秀的V8解释器,javascript执行速度和内存占有率表现非常优秀.对于html ...

  3. Spark1

    Spark集群 0.0体验安装Spark在集群单节点 1.tar tar -xzvf xxx.tgz -C /soft/ ln -s /soft/spark-2.1.0-bin-hadoop2.7 / ...

  4. BZOJ 3931 / Luogu P3171 [CQOI2015]网络吞吐量 (最大流板题)

    题面 中文题目,不解释: BZOJ传送门 Luogu传送门 分析 这题建图是显然的,拆点后iii和i′i'i′连容量为吞吐量的边,根据题目要求,111和nnn的吞吐量看作∞\infty∞. 然后用di ...

  5. 001_89C52之_Proteus_ADC0809采集电压

    一)使用ADC0809采集直流电压 1. 第一个数码管显示的是采样输入口 2. 后面三位是采样电压 (二)使用ADC0809进行交流电的采样 1. 先进行交流电降压,即用变压器降压后使用整桥电路进行整 ...

  6. .net大文件上传

    ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现. 下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压. ASP.NE ...

  7. luoguP4778 Counting swaps

    题目链接 题解 首先,对于每个\(i\)向\(a[i]\)连边. 这样会连出许多独立的环. 可以证明,交换操作不会跨越环. 每个环内的点到最终状态最少交换步数是 \(环的大小-1\) 那么设\(f[i ...

  8. 7.26T2某不科学的迷你激光炮

    题目描述 身为课代表的她,下课总愿意帮老师发作业.老师的作业好多好多啊,一天 下来,她下课休息时间也无几了…… 要是天花板上有一只激光炮该多好啊!把作业塞到激光炮里面,轰——一排 同学该都拿到作业了吧 ...

  9. 3.5寸1.44M软盘结构

    结构: 划分: 簇:磁盘驱动器在向磁盘读取和写入数据时,要以扇区为单位.在磁盘上,DOS操作系统是以“簇”为单位为文件分配磁盘空间的.硬盘的簇通常为多个扇区,与磁盘的种类.DOS 版本及硬盘分区的大小 ...

  10. Python 不覆盖输入txt 读取txt

    不覆盖输入: with open('1.txt','rt')as f: data=f.read() print(data+"\n") 读取txt: with open('1.txt ...