预备知识
- 图:由点集合V和线集合E组成。
- 分配:线集合E的子集,使得分配集合M里的线所连着的点互不重合。换句话说,没有一个V里面的点同时与两条或两条以上的M里面的线相连。
- 不可扩展分配:当E集合中不存在可以被加入到M集合中的线时,称M集合为不可扩展分配。
- 最大分配:顾名思义,M集合包含的线最多的分配被称为最大分配
- 完美分配:当最大分配连接了所有的V集合内的点时,称该分配为完美分配
举个例子:
ABCDEF六个人出去旅游,晚上住酒店分配房间,酒店只有双人间。连线代表着两人愿意同房,如图1所示。图2则是一个分配,并且是不可扩展分配,我们没办法再把任何一条蓝线变红却保证分配集合里的线所连着的点互不重合。但很明显他不是一个完美分配,D跟F没房睡了。图3也是一个分配,但是可扩展的,将C-D变红,得到图4,为不可扩展分配,且是最大分配,同时也是完美分配。
感觉好像很简单是不是?这是因为我们是人,可以很直观的对一个这种图进行分析找到最大分配,但如果让计算机来做这件事呢?如何找到最大分配呢?
交替路径:如果一条路径,起始点和终点没有被M里的线所连接,且组成路径的线是蓝红交替的,则称该路径为可变大路径,只需将路径中的红蓝替换,即可得到新的分配|M'| = |M|+1。例:图2中,F-E-A-B-C-D是一条交换路径,将蓝红调换,变成图4。
有了这个,计算机只需要随机初始化一个分配,不断的寻找未被集合M连接的点所组成的交替路径,更新分配M,最后就可以得到最大分配。
- 二分图:图的特例。点集合V可以被分成两个子集V1和V2,使得子集合内的点两两互不相连。
- 二分权重图:二分图的线集合E中的每条线都被赋予了一个值。
二分图匹配算法
问题描述:找到二分权重图中的一个分配M使得该分配的权重最高。
例子: 张三李四王五赵六孙七,五个人在找工作,一共有五份工作,每个人对应每份工作的工资如下所示,求如何分配才能使五个人赚到的钱最多。
| 工作1 | 工作2 | 工作3 | 工作4 | 工作5 | |
|---|---|---|---|---|---|
| 张三 | 2 | 2 | 3 | 3 | 6 |
| 李四 | 6 | 8 | 9 | 7 | 3 |
| 王五 | 2 | 3 | 6 | 5 | 5 |
| 赵六 | 3 | 5 | 3 | 8 | 6 |
| 孙七 | 5 | 2 | 3 | 6 | 4 |
解法思路: 贪心算法,每个人都选择工资最高的工作,发现重合后,再去找出对应的工资次高的工作,比较选择,循环直到没有重复。但这个思路给人看挺简单的,给计算机看就稍微有点费劲了,所以需要稍微转化一下。
数学表示:为V1中的每个点创建变量x_i. V2中的每个点创建变量y_j. 对于所有的x_i, y_j,在x_i + y_j >= c_ij的前提下,最小化x_1+...x_5 + y_1 + ... + y_5.
解法步骤:
详细解释:第0步相当于利用贪心思想,每个人都找工资最高的工作,用该工资来初始化x_i和y_j。作图,尝试利用当前的匹配线找到完美匹配,若找到完美匹配,则代表找到最优解。这边我们看到,李四和王五的最优解重复了,赵六和孙七的最优解也重复了,所以理所当然的,我们的图不可能存在完美分配。但很明显的,我们可以看出,张三的最优解没有重复,所以张三一定是要去做工作5的,而李四和王五肯定有一个人会做工作3,赵六和孙七肯定有一个人会做工作4,所以剩下的就是决定谁去做工作1和工作2会使得损失最小。这个概念抽象对应的是vertex cover(点覆盖),即V的子集合,使得该子集中的点与E中的所有线相连。所以在第2步中,后三列是不需要考虑的,但记得我们的目标,最小化x_1+...x_5 + y_1 + ... + y_5,这时候我们要在一二列找到最优解的同时不破坏已经找到的后三列最优解,所以需要将y_3,y_4,y_5加上次优解,x_1-x_5减去次优解,然后重复第1步寻找完美分配。
ps: 求最小值的话只需找出最大值并用最大值减去所有元素然后从第0步开始即可。
感悟
算法这东西明明他娘的是学数学的该搞的,学计算机的搞这玩意干嘛啊。。气死了,有一说一,就这个算法,学会很简单,理解其中的数学思维,抽象思维却是难上加难。最开始的问题转化看了我好久,接下来的vertex cover也是,需要很强的概括能力以及抽象能力才能把这个算法变得普适化,反正我也就只是学了个大概,让我自己去写这么一个玩意出来那是万万不可能的。