KM算法——二分图最大权匹配

我们前面学过了二分图匹配的匈牙利算法。但这种算法是针对没有权值的图来说的。

肯定有人想问,没有权值的用匈牙利算法,哪有权值的图要求最大权或最小权匹配呢??

这里就引出了我们今天的主角——KM算法。

这种算法是怎么着呢? 其实最大和最小权匹配都是一样的问题。只要会求最大匹配,如果要求最小权匹配,则将权值取相反数,再把结果取相反数,那么最小权匹配就求出来了。

但问题在这么求最大权匹配呢??

再看这个问题之前我们先来搞清楚几个概念。

one

二分图的带权匹配:二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小。而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最大或最小。二分图的带权匹配与最佳匹配不等价,也不互相包含

这两个的关系比较悬乎。我的理解就是带权匹配是不考虑是不是完备,只求最大或最小权匹配。而最佳匹配则必须在完备匹配的基础上找最大或最小权匹配。

KM算法的运行要求是必须存在一个完备匹配,如果求一个最大权匹配(不一定完备)该如何办?依然很简单,把不存在的边权值赋为0。

KM算法求得的最大权匹配是边权值和最大,如果我想要边权之积最大,又怎样转化?还是不难办到,每条边权取自然对数,然后求最大和权匹配,求得的结果a再算出e^a就是最大积匹配。至于精度问题则没有更好的办法了。

two

二分图最优匹配:对于二分图的每条边都有一个权(非负),要求一种完备匹配方案,使得所有匹配边的权和最大,记做最优完备匹配。(特殊的,当所有边的权为1时,就是最大完备匹配问题)

three。

完备匹配定义     设G=<V1,V2,E>为二部图,|V1|≤|V2|,M为G中一个最大匹配,且|M|=|V1|,则称M为V1到V2的完备匹配。

在上述定义中,若|V2|=|V1|,则完备匹配即为完美匹配,若|V1|<|V2|,则完备匹配为G中最大匹配。

KM算法

KM算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。设顶点Xi的顶标为A[i],顶点Yi的顶标为B[i],顶点Xi与Yj之间的边权为w[i,j]。在算法执行过程中的任一时刻,对于任一条边(i,j),A[i]+B[j]>=w[i,j]始终成立,初始A[i]为与xi相连的边的最大边权,B[j]=0。KM算法的正确性基于以下定理:

设 G(V,E) 为二部图, G'(V,E') 为二部图的子图。如果对于 G' 中的任何边<x,y> 满足, L(x)+ L(y)== Wx,y,我们称 G'(V,E') 为 G(V,E) 的等价子图或相等子图(是G的生成子图)。

若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。

因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和(即不是最优匹配)。所以相等子图的完备匹配一定是二分图的最大权匹配。

算法流程

(1)初始化可行顶标的值

(2)用匈牙利算法寻找完备匹配

(3)若未找到完备匹配则修改可行顶标的值

(4)重复(2)(3)直到找到相等子图的完备匹配为止 

小总结:

KM算法是用来解决最大权匹配问题的,在一个二分图里,左顶点为x,右顶点为y,现对于每组左右连接连接XiYj有权wij,求一种匹配使得所有wij的和最大。

也就是说,最大匹配一定是完美匹配。(完美匹配:二分图的两边点数相同)

如果点数不相同,我们可以通过虚拟点权为0的点来时的点数相同,这也就使这个图变成了完美匹配。

代码实现:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
;
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;
    ; boy < N; ++boy) {
        if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
        int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
        ) {  // 如果符合要求
            vis_boy[boy] = true;
             || 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
    // 每个女生的初始期望值是与她相连的男生最大的好感度
    ; i < N; ++i)
    {
        ex_girl[i] = love[i][];
        ; j < N; ++j)
            ex_girl[i] = max(ex_girl[i], love[i][j]);
    }
    // 尝试为每一个女生解决归宿问题
    ; i < N; ++i)
    {
        fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
        )
        {
            // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
            // 记录每轮匹配中男生女生是否被尝试匹配过
            memset(vis_girl, false, sizeof vis_girl);
            memset(vis_boy, false, sizeof vis_boy);
            if (dfs(i)) break;  // 找到归宿 退出
            // 如果不能找到 就降低期望值
            // 最小可降低的期望值
            int d = INF;
            ; j < N; ++j)
                if (!vis_boy[j]) d = min(d, slack[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;
            }
        }
    }
    // 匹配完成 求出所有配对的好感度的和
    ;
    ; i < N; ++i)
        res += love[ match[i] ][i];
    return res;
}
int main()
{
    while (~scanf("%d", &N)) {
        ; i < N; ++i)
            ; j < N; ++j)
                scanf("%d", &love[i][j]);
        printf("%d\n", KM());
    }
    ;
}

这有一篇博客讲的挺好的。

http://www.cnblogs.com/wenruo/p/5264235.html

Kuhn-Munkres算法的更多相关文章

  1. 二分图匹配--KM算法

    Kuhn-Munkres算法 KM算法,求完备匹配下的最大权匹配,时间复杂度O(\(n^3\)) 所谓的完备匹配就是在二部图中,x点集中的所有点都有对应的匹配 且 y点集中所有的点都有对应的匹配 ,则 ...

  2. acm算法模板(1)

    1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函数 10 1.6 面积 15 1.7 球面 16 1.8 三角形 17 1.9 三维几 ...

  3. Kuhn-Munkres算法。带权二分图匹配模板 (bin神小改版本)

    /****************************************************** 二分图最佳匹配 (kuhn munkras 算法 O(m*m*n)). 邻接矩阵形式 . ...

  4. HDU 2853 最大匹配&KM模板

    http://acm.hdu.edu.cn/showproblem.php?pid=2853 这道题初看了没有思路,一直想的用网络流如何解决 参考了潘大神牌题解才懂的 最大匹配问题KM 还需要一些技巧 ...

  5. ACM-ICPC竞赛模板

    为了方便打印,不再将代码放到代码编辑器里,祝你好运. ACM-ICPC竞赛模板(1) 1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函 ...

  6. HDUOJ---------2255奔小康赚大钱

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

  7. MATLAB实例:Munkres指派算法

    MATLAB实例:Munkres指派算法 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. 指派问题陈述 指派问题涉及将机器分配给任务,将工人分配给 ...

  8. 分配问题与Hungarian算法

    分配问题与Hungarian算法 分配问题 指派问题 匈牙利算法 匈牙利方法是一种能够在多项式时间内解决分配问题(assignment problem)的组合优化算法.它由Harold Kuhn 与1 ...

  9. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

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

  10. 匈牙利算法(Kuhn-Munkres)算法

    这个算法有点难度,一般比较标准的描述网页上也有相关的描述,我在这里就简单的用十分通俗的语言给大家入个门 主要可以结合https://blog.csdn.net/zsfcg/article/detail ...

随机推荐

  1. Flexbox兼容性

    .flex-container{ display: -webkit-box; /* Chrome 4+, Safari 3.1, iOS Safari 3.2+ */ display: -moz-bo ...

  2. Web中的宽和高

    不同的宽高定义 //网页可见区域宽 document.body.clientWidth //网页可见区域高 document.body.clientHeight //网页可见区域宽(包括边线和滚动条的 ...

  3. 【BZOJ】1707: [Usaco2007 Nov]tanning分配防晒霜

    [算法]贪心扫描线(+堆) [题意]给定n头牛有区间[a,b],m个防晒霜值为ai,每个可以使用bi次,每次可以使包含它的区间涂到防晒霜,问最多被涂牛数. [题解] 参考:[bzoj1707]: [U ...

  4. linux学习记录.2.hello world.c

    安装vim,指令: sudo apt-get install vim 建立一个子目录WorkSpace,指令 mkdir WorkSpace 转到该目录下,指令 cd WorkSpace 新建c文件, ...

  5. 残差网络(Residual Network)

    一.背景 1)梯度消失问题 我们发现很深的网络层,由于参数初始化一般更靠近0,这样在训练的过程中更新浅层网络的参数时,很容易随着网络的深入而导致梯度消失,浅层的参数无法更新. 可以看到,假设现在需要更 ...

  6. javashop每次重新部署都要从新安装的问题

    javashop每次重新部署都要从新安装的问题 发现一个问题就是用MyEclipse是部署不上的,用eclipse才行. 这个问题的关键在于javashop有好多文件都是动态生成的,好多配置文件也是在 ...

  7. (1)剑指Offer之斐波那契数列问题和跳台阶问题

    一 斐波那契数列 题目描述: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项. n<=39 问题分析: 可以肯定的是这一题通过递归的方式是肯定能做出来,但是这样会有 ...

  8. python基础===100盏灯的问题

    闪存里有人这样提问这样: 第一轮操作所有电灯,第二轮操作第2盏,第4盏开关,以此类推,第三轮改变编号为3的倍数的电灯,第3盏,第6盏,如果原来那盏灯是亮的,就熄灭它,如果原来是灭的,就点亮它,以此类推 ...

  9. 64_p8

    python2-cotyledon-tests-1.6.7-2.fc26.noarch.rpm 12-Feb-2017 10:28 23182 python2-couchdb-1.0-6.fc26.n ...

  10. Java线上应用故障之CPU占用高排查与定位

    最近线上频繁报警CPU空闲不足,故紧急排查后分享给大家 1.使用top命令,获取占用CPU最高的进程号 2.查看线程号对应的进程信息 命令:ps -ef|grep 22630 3.查看进程对应的线程信 ...