在现实生活中经常会遇见匹配问题需要解决,我们手中有两种资源如何让他们之间的组合最优。
举个例子,你是联谊会的执行人,联谊上有一群男生和一群女生,每个人都对自己心目中的对象有明确要求,如身高籍贯等,你已知了每个人的个人信息和他们提出的要求,怎么才能凑出更多对符合对方期望的配对。
或者,你是租车行的老板,你手上有N台车,各自配置不同,有豪华跑车,有越野型的,有商务SUV等等,每一种类型可能不止一辆。今天来了M位顾客,每位顾客的要求也明确,有的就要租越野车,有的要租SUV。你现在面临的问题就是怎么把顾客和车进行配对,从而使得收益最大化。
上述的两个问题都是二部图匹配的问题,具体说是从一个二部图中找出它的最大匹配。这种问题都可以通过上一篇文章中的匈牙利算法来得到解决。
但是现实生活中有些问题比上述问题更加复杂,比如租车问题中好几台豪华跑车都能满足同一个顾客的要求,但是出于对外观的好恶,顾客对这几台车的出价可能不同。而且每个顾客对每辆车的出价都不同。换句话说,二部图中连接左右节点的边加上了权重。那么,我们现在如何让自己收益最大化。显然匈牙利算法没法解决这个问题,因为它平等的看待每一条边。在此介绍一种新的算法,KM(Kuhn-Munkres Algorithm)算法来解决这种带权二部图中的最优匹配问题。
还是和上一篇文章一样从一个具体的例子来看算法在运行过程中的步骤和思想。
从租车问题说起,现在你有5辆车, y 1 y_1 y1到 y 5 y_5 y5,并且现在来了5位顾客 x 1 x_1 x1到 x 5 x_5 x5。每位顾客给每辆车的一天租金的报价列在右边的标中,如给2号顾客分配4号车,他一天只愿意出3单位的钱,但如果给他分配5号车,他一天愿意出8单位的钱。我们需要计算怎么分配车辆达到最大收益。
KM算法我也看了几天,最难理解的对我而言就是右节点的label的意义。因此这里先不从标准的KM算法讲起,而是从我简化过的"伪KM算法"作为引入来讲解。
伪KM算法
对于每位顾客,首先我们给他们贴上一个label(记为 L ( x i ) L(x_i) L(xi)),记录该顾客身上有多少钱,假设每个顾客只会带自己最高出价那么多的钱,因为再带多了也没用。因此 L ( x i ) = m a x ( w e i g h t ( x i , y j ) ) L(x_i)=max(weight(x_i, y_j)) L(xi)=max(weight(xi,yj)),其中j可以取任意有效值。理想情况下在把每个人的荷包都清空,我们就达到了最大收益,但是经常会遇见冲突,如1号顾客和2号顾客都给5号车出价最高,没法同时满足,因此就要进行妥协。实际上KM算法就是从最理想的状态不断进行妥协的过程。
第一步
和匈牙利的结构类似,还是对于左边的节点一个一个进行处理。首先对 x 1 x_1 x1,直接让他匹配他现在的钱包能承受的最贵的车 y 5 y_5 y5,即要求 L ( x i ) = w e i g h t ( x i , y j ) L(x_i)=weight(x_i,y_j) L(xi)=weight(xi,yj)才能匹配,j可以取任意有效值,此时 y 5 y_5 y5没有被匹配,将 x 1 x_1 x1与 y 5 y_5 y5进行匹配,完成对 x 1 x_1 x1的处理。
第二步
对 x 2 x_2 x2进行匹配,让他匹配他现在的钱包能承受的最贵的车 y 5 y_5 y5,但是现在 y 5 y_5 y5已经被 x 1 x_1 x1匹配了。现在需要让 x 1 x_1 x1或 x 2 x_2 x2其中一人进行妥协,但是 x 1 x_1 x1表示他只盯着他出价最高的 y 5 y_5 y5,同样 x 2 x_2 x2也只盯着他出价最高的 y 5 y_5 y5,两人都没有其它选择,杠上了。如何对他俩进行仲裁?
既然你俩对于 y 5 y_5 y5的归属有争议,那么就进行“竞标”, x 1 x_1 x1和 x 2 x_2 x2都砸出 d d d单位金钱,同时把自己对于 y 5 y_5 y5的出价调低 d d d单位(保证自己永远能买得起 y 5 y_5 y5),看谁最先耐不住。同时不能让其它人占便宜,因此需要大家一起把对 y 5 y_5 y5的出价调低 d d d单位。
那么 d d d如何取值?
首先 d d d从0开始慢慢变大,变到多少才能停?就目前的情况来看, x 1 x_1 x1和 x 2 x_2 x2都有望获得 y 5 y_5 y5,但同样谁也没有把握一定得到 y 5 y_5 y5,因此 x 1 x_1 x1和 x 2 x_2 x2需要给自己留后路,即保证自己能租得起冲突的车除外的所有车。
用公式表达就是 d = m i n ( L ( x i ) − w e i g h t ( x i , y j ) ) d=min(L(x_i)-weight(x_i, y_j)) d=min(L(xi)−weight(xi,yj)), x i x_i xi为起冲突的顾客, y j y_j <