km算法的个人理解
首先相对于上个blog讲的匈牙利算法用于解决无权二分图的最佳匹配,km算法则是在匈牙利算法基础上更进一层的,每条边增加了权值后,真的开始看时有些无厘头,觉得没有什么好方法,但两位牛人Kuhn-Munkras在1957年提出的,而匈牙利算法是在1965年提出的,
终于翻了图书馆3本书的讲解和无数网上牛人的讲解,终于看懂的,这当然是后话.
首先km算法是在匈牙利算法基础上运行的,本质上km算法大致意思就是先将x集合中每条边连接上其所能连接的最大权值边,如果没有冲突,当然是正确的,有的话,也别急,现在我们要做的是将这个ans逐渐缩小,然后将冲突的边调开,直到满足二分图完备匹配(这个地方用匈牙利算法求最大匹配,若最大匹配是完备匹配,就满足)的时候,此时便是正确的答案.
至于如何将冲突的边进行调整,才能使ans缩小得刚好,又能够使得x集合能够找到各自的y取得最大权值,因此我们给每个x,y集合上的点引入一个可行顶标lx[],ly[],当初就是不明白为什么需要引入这两个顶标才搞了很久,顾名思义,可行顶标就是用来判断当前点是否可行,km算法中即根据lx[i]+ly[j]的大小判断是否I,j能够连接.
可能我们先来证明一个定理会更容易理解km算法:
w[I,j]表示i到j的权值,设W=(wij)(i∈x,j∈y),其中排列{jk1,jk2…,jkn},使最大匹配M=(wij)(其中(in,jkn)连接) ,存在{lx[i]},{ly[j]},满足lx[i]+ly[j]>=w[I,j],且其中lx[in]+ly[jkn]=w[In,jn], 最佳匹配的权值和max(sigma(wij))=min(sigma(lx[])+sigma(ly[]))
举个例子好理解:
|
wij |
j1 |
j2 |
j3 |
|
i1 |
3 |
2 |
* |
|
i2 |
2 |
* |
1 |
|
i3 |
* |
1 |
2 |
一开始我们令所有x集合lx[i]=max(w[i,j]),ly[j]=0,则保证lx[i]+ly[j]>=w[i,j],然后我们通过一个表格来表示x和y之间的关系,
则lx[1]=3lx[2]=2 lx[3]=2 ly[]=0
然后做一个表格表示lx[i]+ly[j]-w[i,j]
|
lx[i]-ly[j]-w[i,j] |
j1 |
j2 |
j3 |
|
i1 |
0 |
1 |
* |
|
i2 |
0 |
* |
1 |
|
i3 |
* |
1 |
0 |
因为要保证lx[i]+ly[j]>=w[i,j]所以我们只匹配lx[i]+ly[j]=w[i,j]的边,即其他lx[i]+ly[j]>w[i,j]的边先去除.
说明:仔细想想,当前这个情况若满足每个0都在不同行不同列,是不是当前这个情况就是最佳匹配,因为现在每个x都选到了最大的y,显然没有比这个更大的匹配了,不过情况比这个复杂些,其中i1,i2都和j1匹配,产生冲突,所以我们应该修正.
是不是有点感觉了,仔细想想,现在我们应该增大0的个数使得存在不同行不同列的0有n个,因为0即表示可以匹配,所以是不是感觉到可以使用匈牙利算法来找出不同行不同列0的个数,只要等于n即表示当前这个ans=max(sigma(wij))是最优的.
不过当前情况不符合匹配,所以我们要适当缩小ans,使得ans缩小到下一个状态,在这个状态中至少要多出一个0,而且其他边的lx[],ly[]不要影响这些的状态,
因此要得到至少多出一个0,我们得将表格中最小的正整数min=(1,1,1)=1减掉,
现在我们是到i2时发现冲突,因此我们得调整lx,ly,然后重新用匈牙利算法匹配,
{入交错图指入队 如上述第一步中i1,i2入了交错图形成i1-j1-i2,现在将入交错图的x点集合为sx,入交错图的y点集合为sy}
这样我们也就是要将i1或者i2与其他的j匹配,所以我们将sx上的点即i1,i2的lx[]下调1,然后将sy的点即j1的ly[]上调1,
这样的话我们得到
lx[1]=2lx[2]=1 lx[3]=2 ly[1]=1 ly[2]=0 ly[3]=0
|
lx[i]-ly[j]-w[i,j] |
j1 |
j2 |
j3 |
|
i1 |
0 |
0 |
* |
|
i2 |
0 |
* |
1 |
|
i3 |
* |
1 |
0 |
多出一个0,现在匈牙利算法计算时就满足完备匹配了ok
我搞的这个数据不太好,一步到位…,不过足以说明了
然后说明一下为什么这样调保证即使还得继续调整也是正确:每次有匹配冲突时,表示x集合上有一点p无法再插入sx中,我们暂时把它当做入了sx,我们得为他或者其他入交错图的x找到一个匹配,p才能真正入sx. 但是原来的0(原来的边)不能被删除,故我们将sy中的点ly+min这样就保证原来的lx+ly=w,原来的边依旧可以用
其中因为|sx|=|sy|+1;sigma(lx[])+sigma(ly[])比之前减少了min*(|sx|-|sy|)=min
也就是:
对于sx,sy上点:lx-min+ly+min=lx+ly不变
对于sx,非sy上点:lx-min+ly<lx+ly缩小也就使得边多出来
对于非sx,sy上点:lx+ly+min>lx+ly又lx+ly>=w,故lx+ly+min依旧满足>=w
对于非sx,非sy上点:无影响
将{sx}上点lx[i]均-min不是就使得在{sx}与{非sy}之间至少出现一条使得lx[i]+ly[j]=w[i,j],即多出至少一条边,从上述表格形式即多出一个0,而且我们是将下一个多出0的情况找到,故这满足最佳匹配.
因此只要经过有限次的重复上述步骤可达到求得min(sigma(lx[])+sigma(ly[]))
即ans
补上代码:
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int lx[200],ly[200],w[200][200],pre[200];
int n,ans,mi;
bool sx[200],sy[200];
bool path(int p){
sx[p]=1;
int i;
for(i=1;i<=n;i++)
if (!sy[i]&&lx[p]+ly[i]==w[p][i]){
sy[i]=1;//此处要记得将i入sy,否则之后path会挂的...找了很久...
if (pre[i]==0||path(pre[i])){
pre[i]=p;
return 1;
}
}
return 0;
}
int main()
{
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
scanf("%d",&w[i][j]);
w[i][j]=w[i][j];
if (w[i][j]>lx[i]) lx[i]=w[i][j];
}
for(i=1;i<=n;i++){
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
while (!path(i)){
mi=2000000000;
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
if (sx[j]&&!sy[k]){
if (lx[j]+ly[k]-w[j][k]<mi) mi=lx[j]+ly[k]-w[j][k];
}
for(j=1;j<=n;j++) if(sx[j]) lx[j]-=mi;
for(j=1;j<=n;j++) if(sy[j]) ly[j]+=mi;
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
}
}
for(i=1;i<=n;i++)
ans+=lx[i]+ly[i];
printf("%d",ans);
return 0;
}
km算法的个人理解的更多相关文章
- poj3565Ants——KM算法
题目:http://poj.org/problem?id=3565 首先,我们神奇地发现,没有相交边的匹配可以转化为距离和最小的匹配,所以可以使用KM算法求带权匹配: 要求的是距离和最小,所以把边权转 ...
- uva11383 Golden Tiger Claw 深入理解km算法
/** 题目: uva11383 Golden Tiger Claw 深入理解km算法 链接:https://vjudge.net/problem/UVA-11383 题意:lv 思路:lrj训练指南 ...
- KM算法(理解篇)
转载:https://www.cnblogs.com/logosG/p/logos.html(很好,很容易理解) 一.匈牙利算法 匈牙利算法用于解决什么问题? 匈牙利算法用于解决二分图的最大匹配问题. ...
- HDU(2255),KM算法,最大权匹配
题目链接 奔小康赚大钱 Time Limit: 1000/1000MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- 二分图 最大权匹配 km算法
这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最 ...
- KM算法详解+模板
http://www.cnblogs.com/wenruo/p/5264235.html KM算法用来求二分图最大权完美匹配. 本文配合该博文服用更佳:趣写算法系列之--匈牙利算法 现在有N男N女,男 ...
- 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- [置顶] 小白学习KM算法详细总结--附上模板题hdu2255
KM算法是基于匈牙利算法求最大或最小权值的完备匹配 关于KM不知道看了多久,每次都不能完全理解,今天花了很久的时间做个总结,归纳以及结合别人的总结给出自己的理解,希望自己以后来看能一目了然,也希望对刚 ...
- 二分图匹配之最佳匹配——KM算法
今天也大致学了下KM算法,用于求二分图匹配的最佳匹配. 何为最佳?我们能用匈牙利算法对二分图进行最大匹配,但匹配的方式不唯一,如果我们假设每条边有权值,那么一定会存在一个最大权值的匹配情况,但对于KM ...
随机推荐
- 64bit Ubuntu, Android AAPT, R.java
Ubuntu 13.10 aapt: error while loading shared libraries: libstdc++.so.6: cannot open shared object f ...
- Document.defaultView
Document.defaultView 引子 最近愚安在写一个可以将页面上的资源链接转为二维码以方便移动端浏览的chrome插件,由于dom操作并不多,而且作为插件不需要考虑跨 浏览器兼容性,所以并 ...
- 怎么让LinearLayout充满ScrollView
ScrollView里只能放一个元素. 当ScrollView里的元素想填满ScrollView时,使用"fill_parent"是不管用的,必需为ScrollView设置: ...
- ffmpeg 音频转码
大多数厂家摄像机输出的音频流格式都是PCM,有一些场合(比如讲音视频流保存成Ts流)需要将PCM格式转成AAC格式.基本的思路是先解码得到音频帧,再将音频帧编码成AAC格式.编码和解码之间需要添加一个 ...
- BZOJ1692: [Usaco2007 Dec]队列变换
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 594 Solved: 246[Submit][Sta ...
- 【BZOJ】【2190】【SDOI2008】仪仗队
欧拉函数/莫比乌斯函数 Orz iwtwiioi 这个嘛……很明显在同一条线上的两个点一定是满足 x1*k=x2,y1*k=y2,(好吧这个表示方式有点傻逼,懂得就好了)那么这条线上的点只有第一个会 ...
- PAT-乙级-1053. 住房空置率 (20)
1053. 住房空置率 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 在不打扰居民的前提下,统计住房空 ...
- 适合我胃口的angular.js学习资料
断断续续弄了半年的ANGULAR.JS学习资料,网上下载了N多资料,测试了很多次. 现在只能算是入门,因时间问题,现在要转入其它领域. 如果以后要拾起来,下面这个PDF比较对我胃口. <Angu ...
- hdu 1271 整数对
看了别人的解题报告a了, 大致思路就是 A=a+b*10^k+c*10^(k+1) B=a+c*10^k (在A中取出一位数后) N=A+B=2*a+b*10^k+11*c*10^k 这样就好做了,再 ...
- Oracle的学习二:表管理(数据类型、创建/修改表、添加/修改/删除数据、数据查询)
1.Oracle表的管理 表名和列名的命名规则: 必须以字母开头: 长度不能超过30个字符: 不能使用oracle的保留字: 只能使用如下字符:A-Z, a-z, 0-9, $, # 等. Oracl ...