匈牙利算法 (poj1422-Air Raid,poj1469-COURSES)

首先注意区分“最小路径覆盖”(minimum path cover)和“最小边覆盖”(minimum edge cover)以及“最小点覆盖”(minimum vertex cover)之间的区别。详细资料可以查询Wiki。

最小路径覆盖可以转化为二分图的最大匹配(maximum bipartite matching) 。公式为最小路径覆盖数=原图节点数-二分图最大匹配数。

求最大匹配的方法有两种:一是将二分图增添两个节点(source起点和sink终点)构造一个流网络(flow network),然后就可以按求最大流的算法来计算,基本的算法有Ford-Fulkerson算法。不过这样实现起来比较麻烦,下面着重介绍第二种方法:匈牙利算法(Hungarian algorithm )

 

匈牙利算法其实和基于增广路径(augmenting path)的最大流算法是比较相似的。不同点在于:

  一,匈牙利算法不需要构造流网络,也就是说不需要增添节点,并且二分图是无向图,不需要转换为流网络中的有向图。

  二,匈牙利算法的增广路径(设为P)有附加条件:P的第一条边必须是尚未匹配的边,第二条边是已经匹配的边,如此未匹配和已匹配的边交替出现,最后一条边仍然是未匹配边(注意P可以是只有一条未匹配边的路径)。根据增广路径的附加条件可以看出一个特点:P的未匹配边一定比已匹配边多一条。

  三,匈牙利算法依次对二分图的半边(左半边或者右半边,条件是节点数少的一边)的每个节点开始找增广路径,如果找到则取反:未匹配的边变成匹配边,已匹配边去掉匹配关系。这样的结果是路径P的匹配边数量增加一条,未匹配边数量减少一条。寻找增广路径的方法为DFS或者BFS递归。

  四,当二分图中不存在增广路径时即产生最大匹配数。

匈牙利算法的实质就是找增广路径,并对增广路径做取反操作,直到没有增广路径为止。

 

匈牙利算法的基本流程:

初始时最大匹配为空
  
for 二分图左半边的每个点i
      
do 从点i出发寻找增广路径。如果找到,则把它取反(即增加了总了匹配数)。


下面是poj1422匈牙利算法的实现:

Code


poj1469匈牙利算法:

Code

参考:用匈牙利算法求二分图的最大匹配

   http://www.matrix67.com/blog/archives/39

   http://blog.163.com/baobao_zhang@126/blog/static/48252367200862682748461/

     http://old.blog.edu.cn/user3/Hailer/archives/2007/1829623.shtml

 


PS:很神奇的一件事,Air Raid这题用EK最大流算法在zoj上WA,在poj上居然AC了。。。以下是poj1422EK算法的实现:

Code

 

 

posted @ 2009-07-13 08:55  MyShowTime  阅读(1591)  评论(1编辑  收藏  举报