网络流问题-最小费用最大流

      继续沿着2017华为软件精英挑战赛,查阅了一些【最小费用最大流】相关的资料。今年的赛题归结为:组合优化+最小费用最大流两个子问题,给定的服务器选址下求出最小费用最大流作为底层的算法支撑会很好提升最终的结果,服务器的选址这个组合优化问题有很多解决方案,我采用遗传算法有较好收敛(参考上一篇博文“遗传算法”)。

      先列出一堆不错的博文:

          1.   http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml,介绍SPFA(我用的dijkstar算法)

          2.   http://blog.csdn.net/pi9nc/article/details/23339111 , 介绍Ford_Fulkerson算法,EK算法,DInic算法 

      网上关于 “网络流问题-最小费用最大流” 的资料,基本都是应用于简单的有向图模型,今年的题目我认为必须要用到无向图的“最小费用最大流”解决方案。

      下面是搜罗的有向图里面最小费用最大流的详细讲解,先看看以下关于有向图的该问题解决思路:


      咋一看,上面的解法对“最小费用最大流”比较好,但是无向图中已经存在反向边,或者可以把无向图的边看成是方向相反的两条有向边,那么在无向图中 “添加反向的权重”应该怎么处理呢?实际上和有向图一样,这时添加的反向边不能和原来的边叠加, 细细看这篇博文http://blog.csdn.net/fobdddf/article/details/19615651  ,里面介绍详细....

      上面的博文采用SPFA算法解决最小费用问题(最短路径问题),我尝试一番后,配合遗传算法,在第一批次主办方提供的测试用例上能得出最优解(每个用例在迭代1000代出来的结果就已经最优了),但是,注意这个但是,SPFA算法的时间复杂度相较于dijkstar算法大了老大一截,第二批次的测试用例跑起来就很吃力无法满足时间要求。

后续考虑给图分区,或者选用时间复杂度更低的最短路径算法。

       华为这次算法大赛给的题目,看来不是让我们找最优解,而是找一个时间复杂度可以接受的次优解算法。

       博主在思考给图分区的时候,采用dijkstar来做分区,找最短路径的时候只找一个节点的最近的N个点内的点,也就是设置的N个点内没找到想要的点就退出dijk,慢慢地,发现dijkstar还可以这么用:1. dijkstar可以从源点找到汇点的最短路径,也可以找从汇点出发距离最近的源点(边依然指向汇点,而不是从汇点指出去),这样可以大大减少dijk被调用的次数,因为从汇点出发只要找到最近的源点dijk就退出了,即只需调用(未饱和)汇点个数次dijk, 如果从源点出发要调用所有源点个数次dijk, 本次赛题平均汇点个数远远小于平均源点个数(实测结果); 2. 从汇点找最近源点的路径,使用流的效果等同于SPFA撤回反向边的效果(实测结果)。参赛群里一些童鞋说遗传迭代次数少, 估计是这底层支撑算法没实现好,我在初级用例上迭代1代时间在30ms左右(种群40个体数),在中级用例上迭代1代时间在150~200ms,高级用例就不大好使了。博主采用启发式搜索的迭代优化(模拟退火调出来的结果比迭代优化差点点,不知道为啥)+遗传的组合,只有初级部分中级用例能跑进遗传,其他只能在迭代优化里晃悠出一个解。由于是迭代优化,为了避免解在困在局部最优里,启发式策略中考虑的邻域函数找到的尝试解要有一定随机性,不能往特定方向搜索,这种随机性不同于遗传算法的基因随机变异,只是局部范围的随机,只是领域内部的随机部分尝试,也就是给出一个领域后,就随机地尝试领域里一定百分比的待求解,这样能大大增加搜索区间范围并且降低困在局部最优的几率。

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值