对于二分图,我们可以用匈牙利来求出来最大匹配,但是如果给定每条边一个权值,我们要求这张图的最大匹配最大(小)权,单纯的用匈牙利就没法解决了,当然用费用流也可以做,但是代码较长,在处理完全二分图的时候时间也较长。

  我们这时引入一个新的算法,就是KM。

  对于KM算法,我们引入顶标概念,规定每个点都有顶标,且左面的点(二分图的左右)的顶标设成X[I],右面的设成Y[I],w[i,j]代表i-->j这条边的权值(我们这里

求最大权值和),那么满足对于任意边,x[i]+y[j]>=w[i,j],那么,我们最后肯定可以找到一种匹配方式(完备匹配),使得这种方式中的每一条边都满足x[i]+y[j]=w[i,j]那么这种匹配方式一定是该二分图的最大权值匹配,因为x[i]+y[j]>=w[i,j],我们取到了w[i,j]的上限,所以是最大权值的。

  那么我们给x[i],y[j]设初值的时候,因为要满足对于所有边x[i]+y[j]>=w[i,j],所以我们将x[i]设成max(w[i,k])将y[i]设成0,这样就满足了。

  那么我们也需要一个点一个点的匹配,类似于匈牙利,就是对于满足x[i]+y[j]=w[i,j]的边才算一组匹配,这样我们就得到了一组可行解。

function match(i:longint):boolean;
var
j :longint;
begin
fx[i]:=true;
for j:= to m do
if (w[i,j]=tx[i]+ty[j]) and (not fy[j]) then
begin
fy[j]:=true;
if (link[j]=) or (match(link[j])) then
begin
link[j]:=i;
exit(true);
end;
end;
exit(false);
end;

  当前的可行解可以构成一张图,包含2*m个点和m个边(交错树),但是当前的可行解不一定是最终的解,可能最后答案的一些边不在当前集合中,这时我们需要更新顶标,使得更多的点可以来更新答案。

  那么我们设一个c,使当前所有在交错树中的X[i]减去c,使y[i]加上c,那么我们可以得到一些性质:

1.两端都在交错树中的边(i,j),X[i]+Y[j]的值没有变化。也就是说,它原来属于交错树,现在仍属于交错树。
2.两端都不在交错树中的边(i,j),X[i]和Y[j]都没有变化。也就是说,它原来属于(或不属于),现在仍属于(或不属于)交错树。
3.X端不在交错树中,Y端在交错树中的边(i,j),它的X[i]+Y[j]的值有所增大。它原来不属于交错树,现在仍不属于交错树。
4.X端在交错树中,Y端不在交错树中的边(i,j),它的X[i]+Y[j]的值有所减小。也就说,它原来不属于交错树,现在可能进入了交错树,因而可以更新了答案。
那么我们要使至少一条边进入答案,这时我们的c的取值就是min(x[i]+y[j]-w[i,j]),i在交错树中,j不在交错树中,所以我们得到了更新顶标的过程
procedure update;
var
d :longint;
i, j :longint;
c :longint;
begin
c:=maxlongint;
for i:= to n do if fx[i] then
for j:= to m do if not fy[j] then c:=min(c,tx[i]+ty[j]-w[i,j]); for i:= to n do if fx[i] then dec(tx[i],c);
for i:= to m do if fy[i] then inc(ty[i],c);
end;

那么这样一来到最后我们就可以得到这张图的最大权值匹配了,最小只需取相反数即可

附主程序

procedure main;
var
i, j :longint;
begin
for i:= to n do
for j:= to m do
tx[i]:=max(tx[i],w[i,j]); for i:= to n do
while true do
begin
fillchar(fx,sizeof(fx),false);
fillchar(fy,sizeof(fy),false);
if match(i) then break else update;
end; for j:= to m do ans:=ans+w[link[j],j];
writeln(ans);
end;

KM算法讲解的更多相关文章

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

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

  2. HDU2255 奔小康赚大钱 (最大权完美匹配) 模板题【KM算法】

    <题目链接> 奔小康赚大钱 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊 ...

  3. 二分图最佳匹配KM算法 /// 牛客暑期第五场E

    题目大意: 给定n,有n间宿舍 每间4人 接下来n行 是第一年学校规定的宿舍安排 接下来n行 是第二年学生的宿舍安排意愿 求满足学生意愿的最少交换次数 input 2 1 2 3 4 5 6 7 8 ...

  4. KM算法萌新讲解篇

    KM算法   首先了解问题:也就是最大权值匹配: 二分图里,边带了权值,求整幅图里匹配最大/最小的权值 因为接触匈牙利算法的时候看的是找对象系列的博文,所以也自己写一发找对象的博文吧: 算法背景: 信 ...

  5. 二分图带权匹配、最佳匹配与KM算法

    ---------------------以上转自ByVoid神牛博客,并有所省略. [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和 ...

  6. km算法的个人理解

    首先相对于上个blog讲的匈牙利算法用于解决无权二分图的最佳匹配,km算法则是在匈牙利算法基础上更进一层的,每条边增加了权值后,真的开始看时有些无厘头,觉得没有什么好方法,但两位牛人Kuhn-Munk ...

  7. 【原创】我的KM算法详解

    0.二分图 二分图的概念 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V, E)是一个无向图.如果顶点集V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在X中,另一个在Y ...

  8. 二分图带权匹配 KM算法与费用流模型建立

    [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小.而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最大 ...

  9. KM算法详解[转]

    KM算法详解 原帖链接:http://www.cnblogs.com/zpfbuaa/p/7218607.html#_label0 阅读目录 二分图博客推荐 匈牙利算法步骤 匈牙利算法博客推荐 KM算 ...

随机推荐

  1. scidb

    貌似是给科学家用的数据库,暂不研究

  2. git - work flow

    git status – Make sure your current area is clean. git pull – Get the latest version from the remote ...

  3. ajax 异步刷新,需要填写的参数

    参数 options 类型:Object 可选.AJAX 请求设置.所有选项都是可选的. ******* async 类型:Boolean 默认值: true.默认设置下,所有请求均为异步请求.如果需 ...

  4. ubuntu 和 centOS 的apache设置

    更改ubuntu的网站访问根目录: 在sudo gedit /etc/apache2/sites-enabled/000-default,把 DocumentRoot /var/www      #这 ...

  5. C#中System.DBNull的问题

    今天写一个C#的数据库Demo,第一个功能,用户登录,数据库中用户表(Staff)最后一个字段ZP(呵呵,PowerDesigner中文直接翻译的)照片字段为空, 我的登录逻辑是通过用户名以及密码查询 ...

  6. 关于<!DOCTYPE html>的学习(转)

    DOCTYPE是对Document type的缩写,说明用XHTML或者HTML是什么版本的.必须出现在<html>标签的前面,不需要关闭标签. <!DOCTYPE>声明不是标 ...

  7. WEBSTORM中html文件运行之后出现乱码的问题解决

    出现如下问题: 解决方案: 1.点击"文件编码" 2.选择GBK 3.点击Reload. 4.此时,源代码中的中文字体会变成乱码,把这些乱码重新输入成原先的中文.然后运行html文 ...

  8. C语言单元测试

    转自http://blog.csdn.net/colin719/article/details/1420583 对于敏捷开发来说,单元测试必不可少,对于Java开发来说,JUnit非常好,对于C++开 ...

  9. php获取微信token和ticket并返回签名

    jssdk.php页,主要获取token和ticket <?php /* * 微信公众号后台里获取appId和appSecret,并在公众号后台=>安全中心=>IP白名单中设置当前页 ...

  10. Xshell出现要继续使用此程序必须应用到最新的更新或使用新版本

    资源可以用,但是安装完成后启动会报错:“要继续使用此程序,您必须应用最新的更新或使用新版本” 解决办法先修改你电脑时间为前一年(2017 1月),然后就可以打开xshell了,打开后"工具& ...