KM算法详解+模板

大佬讲的太好了!!!太好了!!!

转载自:http://www.cnblogs.com/wenruo/p/5264235.html

KM算法用来求二分图最大权完美匹配。

本文配合该博文服用更佳趣写算法系列之--匈牙利算法

本文没有给出KM算法的原理,只是模拟了一遍算法的过程。另,博主水平较差,发现问题欢迎指出,谢谢!!!!

现在有N男N女,有些男生和女生之间互相有好感,我们将其好感程度定义为好感度,我们希望把他们两两配对,并且最后希望好感度和最大。

怎么选择最优的配对方法呢?

首先,每个女生会有一个期望值,就是与她有好感度的男生中最大的好感度。男生呢,期望值为0,就是……只要有一个妹子就可以啦,不挑~~

这样,我们把每个人的期望值标出来。

接下来,开始配对。

配对方法:

我们从第一个女生开始,分别为每一个女生找对象。

每次都从第一个男生开始,选择一个男生,使男女两人的期望和要等于两人之间的好感度

注意:每一轮匹配每个男生只会被尝试匹配一次!

具体匹配过程:

==============为女1找对象===============

(此时无人配对成功)

根据 “男女两人的期望和要等于两人之间的好感度”的规则

女1-男1:4+0 != 3

女1-男3:4+0 == 4

所以女1选择了男3

女1找对象成功

==============为女1找对象成功============

==============为女2找对象===============

(此时女1—男3)

根据配对原则,女2选择男3

男3有主女1,女1尝试换人

我们尝试让女1去找别人

尝试失败

为女2找对象失败!

==============为女2找对象失败============

这一轮参与匹配的人有:女1,女2,男3。

怎么办???很容易想到的,这两个女生只能降低一下期望值了,降低多少呢?

这轮

比如:女1选择男1,期望值要降低1。 女2选择男1,期望值要降低1。 女2选择男2,期望值要降低2。

于是,只要期望值降低1,就有妹子可能选择其他人。所以妹子们的期望值要降低1点。

同时,刚才被抢的男生此时非常得意,因为有妹子来抢他,于是他的期望值提高了1点(就是同妹子们降低的期望值相同)。

于是期望值变成这样(当然,不参与刚才匹配过程的人期望值不变)

==============继续为女2找对象=============

(此时女1—男3)

女2选择了男1

男1还没有被配对

女2找对象成功!

==============为女2找对象成功=============

==============为女3找对象===============

(此时女1—男3,女2-男1)

女3没有可以配对的男生……

女3找对象失败

==============为女3找对象失败============

此轮只有女3参与匹配

此时应该为女3降低期望值

降低期望值1的时候,女3-男3可以配对,所以女3降低期望值1

==============继续为女3找对象============

(此时女1—男3, 女2-男1)

女3相中了男3

此时男3已经有主女1,于是女1尝试换人

女1选择男1

而男1也已经有主女2,女2尝试换人

前面说过,每一轮匹配每个男生只被匹配一次

所以女2换人失败

女3找对象再次失败

==============为女3找对象失败============

这一轮匹配相关人员:女1,女2,女3,男1,男3

此时,只要女2降低1点期望值,就能换到男2

(前面提过 只要任意一个女生能换到任意一个没有被选择过的男生所需要降低的最小值)

我们把相应人员期望值改变一下

==============还是为女3找对象============

(此时女1—男3, 女2-男1)

女3选择了男3

男3有主女1,女1尝试换人

女1换到了男1

男1已经有主女2,女2尝试换人

女2换人男2

男2无主,匹配成功!!!

==============为女3找对象成功=============

匹配成功!!!撒花~~

到此匹配全部结束

此时

女1-男1,女2-男2,女3-男3

好感度和为最大:9

虽然不停换人的过程听起来很麻烦,但其实整个是个递归的过程,实现起来比较简单。比较复杂的部分就是期望值的改变,但是可以在递归匹配的过程中顺带求出来。

模板(带详细注释)(入门题:HDU2255(复杂度应该是O(N^3)

 #include <iostream>
#include <cstring>
#include <cstdio> using namespace std;
const int MAXN = ;
const int INF = 0x3f3f3f3f; int love[MAXN][MAXN]; // 记录每个妹子和每个男生的好感度
int ex_girl[MAXN]; // 每个妹子的期望值
int ex_boy[MAXN]; // 每个男生的期望值
bool vis_girl[MAXN]; // 记录每一轮匹配匹配过的女生
bool vis_boy[MAXN]; // 记录每一轮匹配匹配过的男生
int match[MAXN]; // 记录每个男生匹配到的妹子 如果没有则为-1
int slack[MAXN]; // 记录每个汉子如果能被妹子倾心最少还需要多少期望值 int N; bool dfs(int girl)
{
vis_girl[girl] = true; for (int boy = ; boy < N; ++boy) { if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次 int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy]; if (gap == ) { // 如果符合要求
vis_boy[boy] = true;
if (match[boy] == - || dfs( match[boy] )) { // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
match[boy] = girl;
return true;
}
} else {
slack[boy] = min(slack[boy], gap); // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
}
} return false;
} int KM()
{
memset(match, -, sizeof match); // 初始每个男生都没有匹配的女生
memset(ex_boy, , sizeof ex_boy); // 初始每个男生的期望值为0 // 每个女生的初始期望值是与她相连的男生最大的好感度
for (int i = ; i < N; ++i) {
ex_girl[i] = love[i][];
for (int j = ; j < N; ++j) {
ex_girl[i] = max(ex_girl[i], love[i][j]);
}
} // 尝试为每一个女生解决归宿问题
for (int i = ; i < N; ++i) { fill(slack, slack + N, INF); // 因为要取最小值 初始化为无穷大 while () {
// 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止 // 记录每轮匹配中男生女生是否被尝试匹配过
memset(vis_girl, false, sizeof vis_girl);
memset(vis_boy, false, sizeof vis_boy); if (dfs(i)) break; // 找到归宿 退出 // 如果不能找到 就降低期望值
// 最小可降低的期望值
int d = INF;
for (int j = ; j < N; ++j)
if (!vis_boy[j]) d = min(d, slack[j]); for (int j = ; j < N; ++j) {
// 所有访问过的女生降低期望值
if (vis_girl[j]) ex_girl[j] -= d; // 所有访问过的男生增加期望值
if (vis_boy[j]) ex_boy[j] += d;
// 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
else slack[j] -= d;
}
}
} // 匹配完成 求出所有配对的好感度的和
int res = ;
for (int i = ; i < N; ++i)
res += love[ match[i] ][i]; return res;
} int main()
{
while (~scanf("%d", &N)) { for (int i = ; i < N; ++i)
for (int j = ; j < N; ++j)
scanf("%d", &love[i][j]); printf("%d\n", KM());
}
return ;
}

二分图最大权值匹配 KM算法 模板的更多相关文章

  1. HDU2255-奔小康赚大钱-二分图最大权值匹配-KM算法

    二分图最大权值匹配问题.用KM算法. 最小权值的时候把权值设置成相反数 /*-------------------------------------------------------------- ...

  2. 【模板】二分图最大权完美匹配KM算法

    hdu2255模板题 KM是什么意思,详见百度百科. 总之知道它可以求二分图最大权完美匹配就可以了,时间复杂度为O(n^3). 给张图. 二分图有了边权,求最大匹配下的最大权值. 所以该怎么做呢?对啊 ...

  3. 二分图最大权完美匹配KM算法

    KM算法二分图 KM求得二分图与普通二分图的不同之处在于:此二分图的每条边(男生女生)上都附了权值(好感度).然后,求怎样完美匹配使得权值之和最大. 这,不止一般的麻烦啊. 可以通过一个期望值来求. ...

  4. HDU 2255 KM算法 二分图最大权值匹配

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

  5. POJ 2400 Supervisor, Supervisee(KM二分图最大权值匹配)题解

    题意:n个老板n个员工,先给你n*n的数据,i行j列代表第i个老板第j喜欢的员工是谁,再给你n*n的数据,i行j列代表第i个员工第j喜欢的老板是谁,如果匹配到第k喜欢的人就会产生一个分数k-1.现在让 ...

  6. 奔小康赚大钱 HDU - 2255(最大权值匹配 KM板题)

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

  7. 牛客多校第五场 E room 二分图匹配 KM算法模板

    链接:https://www.nowcoder.com/acm/contest/143/E来源:牛客网 Nowcoder University has 4n students and n dormit ...

  8. hdu 3722 二分图 最优完备匹配 KM算法

    这题只要想到是最优完备匹配就行了: 题意:给出n个字符串,若两两相连,将前一个反置添加到后一个后面,相连的值为两个字串从头开始相等的字符个数: 问如何匹配得出最大值: 思路:建图,套模板. 代码: # ...

  9. 【模板】二分图最大权完美匹配(KM算法)/洛谷P6577

    题目链接 https://www.luogu.com.cn/problem/P6577 题目大意 给定一个二分图,其左右点的个数各为 \(n\),带权边数为 \(m\),保证存在完美匹配. 求一种完美 ...

随机推荐

  1. vue-vli3创建的项目配置热更新

    vue-vli3创建的项目配置热更新 问题描述:使用vue-cli3创建的项目,修改代码之后,浏览器页面不会自动刷新,然而之前使用webpack初始化的vue项目修改代码之后浏览器会重新加载一下,因为 ...

  2. 3.CAS原子操作

    什么是原子性操作,按照官方的解析:原子操作不能在一个中间操作中停止,要么全部成功要么全部失败.(An atomic action cannot stop in the middle: it eithe ...

  3. SpringBoot 思维导图

  4. (转)linux shell单引号、双引号及无引号区别

    原文:http://blog.csdn.net/woshizhangliang999/article/details/50132265 3.描述linux shell中单引号.双引号及不加引号的简单区 ...

  5. Spark on Yarn运行错误:Yarn application has already ended! It might have been killed or unable to launch application master

    Spark on Yarn模式运行错误: bin/spark-shell --master yarn --deploy-mode client #报错 ​ 查看8088页面上的工作日志 错误原因:在执 ...

  6. 关于GitHub在VS中出现“已经存在master版本,无法……”的错误解决方案

    引用:http://www.cnblogs.com/SmallZL/p/3637613.html(这篇已经很详细说明如何使用Vs+GitHub),我这里做补充: VS2013已经集成了Git一部分控件 ...

  7. NPOI之C#下载Excel

    Java中这个类库叫POI,C#中叫NPOI,很多从Java一直到.Net平台的类库为了区别大部分都是在前面加个N,比如Hibernate和NHibernate. npoi下载地址 一.使用NPOI下 ...

  8. 6、图标:icon

    1.图标 /* ---html----*/ <ion-content text-center class="icons-basic-page"> <ion-row ...

  9. HashMap和Hashtable存放null

    Hashmap是可以放key为null的,Hashtable不能放key为null.hashtable放key为null会报空指针异常 1. hashmap put方法源码 public V put( ...

  10. foreach的基本语法

    有一个布尔型循环是专门用来循环数组的.这个循环的基本语法就是foreach基本语法 foreach( 要循环的数组变量 as [键变量 =>] 值变量){ //循环的内容 } 这是一个固定用法, ...