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

  我们这时引入一个新的算法,就是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. bugku 字符正则

    字符?正则? <?php highlight_file('2.php'); $key='KEY{********************************}'; $IM= preg_mat ...

  2. Selenium PageFactory页面工厂

    使用Selenium PageFactory页面工厂的好处是: 当页面元素的位置发生变化时, 我们只需要去修改id或者xpath, 而不用去修改测试用例. import org.openqa.sele ...

  3. 03-Mysql数据库----安装与管理

    本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的 ...

  4. 阿里云SLB上http强制跳转到https问题处理

    背景: 最近一客户有一个需求,需要将外网所有http访问请求强制跳转到https,公网出口使用阿里云SLB,证书放在SLB上,SLB后端实例为ECS(webserver)web服务使用nginx, 网 ...

  5. LeetCode 74——搜索二维矩阵

    1. 题目 2. 解答 若矩阵为空,比如 [], [[]],此时直接返回 false. 若目标值小于矩阵第一个元素或者大于矩阵最后一个元素,则目标值不在矩阵范围内,直接返回 false. 其他情况下, ...

  6. BZOJ 4184 shallot 线性基+分治

    Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且让小葱从 ...

  7. NO11——01背包

    # include <stdio.h> # include <stdlib.h> # include <string.h> # define max(x,y) x& ...

  8. AtomicIntegerFieldUpdater使用

    假设现在有这样的一个场景: 一百个线程同时对一个int对象进行修改,要求只能有一个线程可以修改. 看看下面程序是否正确: private static int a = 100; private sta ...

  9. Flink源码解读之状态管理

    一.从何说起 State要能发挥作用,就需要持久化到可靠存储中,flink中持久化的动作就是checkpointing,那么从TM中执行的Task的基类StreamTask的checkpoint逻辑说 ...

  10. 【转】IBatis.Net项目数据库SqlServer迁移至Oracle

    转自:http://www.2cto.com/database/201312/265514.html 最近完成了一个(IBatis.Net+MVC)项目的数据库+代码迁移工作,可把我折腾得~~~ IB ...