写完这一章,大概二分图的匹配问题也该完结了吧。
其实我自己现在对KM算法也是刚刚理解,有理解不到位之处还请大家指出。
KM算法:求在一个二分图的完备匹配中的最大权值匹配的算法。(下文简称为最佳完备匹配)
似乎跟匈牙利算法有点相似,
所以我们要引入一个基于匈牙利算法的一种算法,叫做KM算法。
步骤如下:
首先用邻接矩阵存储二分图,注意:如果只想求最大权值匹配而不要求是完备匹配的话,请把各个不相连的边的权值设置为0
之后进行下述步骤:
1.运用贪心算法初始化标杆。
2.运用匈牙利算法找到完备匹配。
3.如果找不到,则通过修改标杆,增加一些边。
4.重复2,3的步骤,找到完备匹配时可结束。
不得不说整个博文时间跨度到了一天……
继续写……
标杆分为X标杆和Y标杆,一般我们把比较少的点放在X标杆一侧。
这样进行算法:
首先要初始化两个标杆分别为X标杆和Y标杆,X标杆初始化为与之相连的最大边权,Y标杆初始化为0,且直接加入拥有最大边权的边。如果发现此时的匹配就是完备匹配,那么直接退出,否则进行标杆的更改。从第一个节点开始扫描,如果有合法的增广路,那么将其反选,扩充路径,如果该节点没有合法的增广路,那么则将增广路上的所有的X标杆上的点加入点集S,将Y标杆上的所有点加入点集T,从S和不在T集合中的点里面,计算d=min{L(x)+L(y)-w(x,y)};计算后,将在S点集内的x的顶标减d,在T的y的顶标加d。并将目前没有加入二分图的权值和等于顶标和的边作为未匹配边加入到二分图中,然后再在该节点寻找增广路,如果还是没有,则再次通过更改标杆来增加边,直到有增广路出现为止。之后重复寻找增广路的步骤以及更改标杆的步骤,如果出现了完备匹配,那么直接退出。
我认为:求d的过程是把xy的顶标和及其权值相差最小的边加入到二分图中,而修改顶标的过程是使得其顶标之和等于新增入的边权,并使得之前选择的那些边仍然存在(即其顶标和仍等于权值和)。
看得有点绕?
我们来看一下强行手工模拟:
有邻接矩阵如下:
x1 x2 x3 x4 x5
y1 7 3 14 19 23
y2 8 10 15 18 20
y3 6 8 12 16 19
y4 4 9 13 20 25
y5 2 7 12 10 15
非常完美的一个邻接矩阵,其中斜体为边权最大值。下面我们按照上面的晕乎乎的步骤来进行模拟吧。
初始化标杆使X标杆的值为斜体字的值。

连接每条边并且使得x1和y3匹配,然后遍历x2,发现x2找不到合法增广路。

把不合法路径上的x点都归为点集S,y点都归为T,将不在T中的y点和在S中的点尝试进行加边。

找到两条边,更新顶标之后,成功形成增广路,运用匈牙利算法反选。

给x3找一个合法的增广路,一下就找到了,直接反选,结束。





之后的步骤就如同图上所说。
代码已经写出:

#include <iostream>
#include <ctime>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iomanip>
#include <stack>
using namespace std;
int w[1005][1005];
const int inf=(1<<20)-1;
int m,n;//n左m右
int cx[1005],cy[1005];//顶标
bool usex[1005],usey[1005];//本回合使用的x,y
int link[1005];//link[i]=x代表:在y图中的i与x相连
bool dfs(int u){usex[u]=1;for(int i=1;i<=m;i++)if(!usey[i]&&cx[u]+cy[i]==w[u][i]){usey[i]=1;if(link[i]==-1||dfs(link[i])){//注意这里要搜link[i]而不是i,因为我们只搜索x侧的,不需要搜索y侧的 link[i]=u;return 1;   }}
return 0;
}
int KM(){memset(cy,0,sizeof(cy));memset(cx,-1,sizeof(cx));for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cx[i]=max(cx[i],w[i][j]);for(int i=1;i<=n;i++){      while(1){int d=inf;memset(usex,0,sizeof(usex));memset(usey,0,sizeof(usey));if(dfs(i))break;for(int i=1;i<=n;i++)if(usex[i])for(int j=1;j<=m;j++)if(!usey[j])d=min(d,cx[i]+cy[j]-w[i][j]);if(d==inf)return -1;for(int i=1;i<=n;i++)if(usex[i])cx[i]-=d;for(int i=1;i<=m;i++)if(usey[i])cy[i]+=d;}}int ans=0;for(int i=1;i<=m;i++){if(~link[i])ans+=w[link[i]][i];}return ans;
}
int main (){while(~scanf("%d%d",&n,&m)){memset(w,0,sizeof(w));memset(link,-1,sizeof(link));int a,b,c;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&w[i][j]);               printf("%d\n",KM());}   return 0;
}

二分图(三)——KM算法相关推荐

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

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

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

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

  3. HDU 2255 奔小康赚大钱 带权二分图匹配 KM算法

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

  4. 奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

    题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.  这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百 ...

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

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

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

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

  7. 带你入门多目标跟踪(三)匈牙利算法KM算法

    匈牙利算法(Hungarian Algorithm)与KM算法(Kuhn-Munkres Algorithm)是做多目标跟踪的小伙伴很容易在论文中见到的两种算法.他们都是用来解决多目标跟踪中的数据关联 ...

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

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

  9. 二分图最大权匹配 KM算法

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

最新文章

  1. Redis 核心篇:唯快不破的秘密
  2. DirectFB实例1--加载一幅图片
  3. 安装yaml报错:ERROR: Cannot uninstall 'PyYAML'.
  4. list-style-type:decimal在IE中显示全是1的解析
  5. 邮箱回执怎么看_考研复试联系导师邮件怎么写?
  6. 用于 Windows8 的 Wijmo Charts 图表控件
  7. 配置ftp方式的yum源的各种排错
  8. winform中通过FileStream实现将文件上传
  9. Java学习笔记四——运算符
  10. 自定义char类型字段
  11. 图卷积神经网络GCN ---如何在交通预测中考虑网络拓扑结构
  12. mysql人脸数据库_人脸数据库汇总
  13. 在Markdown中绘制思维导图
  14. 《2022谷歌开发者大会》参会之旅
  15. 虚拟货币套利怎么处理
  16. 星际争霸2人工智能研究环境SC2LE完全入门指南
  17. 硬盘的读写速度如何计算
  18. 手机端别用谷歌了,好用到爆的小众浏览器你确定不试试
  19. 有逆时针将视频画面旋转90度的方法吗?
  20. 16 tia 内容说明 安装包_TIA Portal V16 软件安装包 安装教程 授权

热门文章

  1. 目前国内公开的手机号段 | 正则资料库
  2. 社保、医保、新农合、城镇保险有什么区别?哪个划算?
  3. pb 调用虹软_记C# 调用虹软人脸识别 那些坑
  4. Java 12 Lanzado:Versoóndescafeinada sin soporte largo plazo
  5. 《Adobe Photoshop CS5中文版经典教程(全彩版)》—第2课2.7节使用海绵工具调整饱和度...
  6. 嵌入式名工程师,为什么有些人月薪8K,而有些人年薪40K值得深思
  7. 热修复系列——Android热修复技术进阶篇
  8. Windows10 WSL2 安装 Ubuntu20.04LTS
  9. CTF术语_ReversePwn(持续更新)
  10. easyexcel 遇到的问题 org.terracotta.statistics.StatisticsManager.tags([Ljava/lang/String;)Ljava/util/Set;