您的位置:首页 > 编程语言 > Java开发

匈牙利算法求二分图的最优匹配(java)

2012-12-06 11:22 246 查看
算法应用场景:

农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术。不幸的是,由于工程问题,每个牛栏都不一样。第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶。上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信息(每头奶牛喜欢在哪些牛栏产奶)。一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏中产奶。问如何匹配奶牛与牛栏以便产奶最大化。

有关匈牙利算法的原理讲解可参考http://imlazy.ycool.com/post.1603708.html,作者通过图形的方式讲解的很详细

匈牙利算法最主要的环节是搜寻增广路径(augmentPath)的过程,假设有两个2分图X和Y,增广路径的搜寻逻辑大致如下:

成员变量定义

匹配集合:M

增广路径中边的集合:path

方法定义:

boolean hasAugmentPath(X x);//判断x是否有增广路径

伪代码描述:

1.for(y:x.getY())//遍历x对应的Y

1.1(x,y)在匹配集合M里

1.1.1 x只对应一个y(即x.getY().size==0) ->return false;//顶点x没有增广路径

1.1.2 x还有其他对应的y ->continue 1

1.2(x,y)不在匹配集合里 ->path集合添加(x,y)这条边

1.2.1 y没有被使用 ->reture true;//找到增广路径

1.2.2 y已经被使用了 ->for(x1:y.getX())//遍历y对应的x

1.2.2.1(y,x1)在path里

1.2.2.1.1 y只有一个x1 ->return false

1.2.2.1.1 y还有其他x1 ->continue 1.2.2

1.2.2.2(y,x1)在匹配集合里 ->path集合添加(y,x1)这条边

递归跳转到1,判断x1是否有增广路径

1.2.2.1 x1有增广路径 ->return true

1.2.2.2 x1没有增广路径 ->path集合中移除(y,x1) continue 1.2.2

1.2.2.3(y,x1)不在匹配集合里 ->continue 1.2.2

1.2.3遍历步骤1.2.2结束依然没有找到增广路径 ->path集合移除(x,y)这条边 continue 1

2.遍历步骤1中所有y依然没有找到增广路径 ->return false//断定x没有增广路径

获取到增广路径之后,需要重新计算匹配集合,方法是将path和M两个集合进行合并,并去掉集合的交集

如path={A,B,C},M={B,C,D}则重新计算出的匹配集合为{A,D}

遍历X中所有的顶点,最终得到的匹配集合就是算法需要的结果

java代码实现:

DateSource类用于封装测试数据源,包括两种,分别是DataSource和DateSource2,两种数据源对应的图形如图所示



Cow类用于封装奶牛信息

Kraal用于封装牛栏信息

Match用于封装奶牛和牛栏的匹配信息

Hungary用于处理匈牙利算法的具体逻辑

Main类用于算法测试

代码可点击URL下载 http://download.csdn.net/detail/javaman_chen/4852597
数据源1测试结果如下:

最大匹配数:3

匹配信息:[D->1, C->3, B->2]

数据源2测试结果如下:

最大匹配数:4

匹配信息:[D->2, B->1, A->3, C->4]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: