最大流问题

问题描述

具体的最大流问题定义、术语以及特性,前人已经描述的很详细了:

我们需要注意以及几个方面:

  • 流量守恒约束:这个无需多言。
  • 后向边(反向边):尾列在头的前面:1→…→i←j→…→n。引入后向边的目的在于寻找到更多可能的增益路径,而无需回溯后寻找,减少时间复杂度。
  • 生成增益路径的方法决定了问题的时间复杂度。——>

增益路径的生成次序如果不恰当,会对方法的效率有巨大的影响。如下:其中U代表某个大正整数。如果沿着路径1→2→3→4对流量0进行增益,得到(b)中值为1的流量;接着沿着路径1→3←2→4对流量0进行增益,得到(c)中值为2的流量。按照上述继续增益,需要2U次迭代才能得到最大的流量值2U。但是,如果沿着路径1→2→4和路径1→3→4增益U仅需要2次迭代。2U和2的巨大差异说明选择高效方法的重要性。

这里写图片描述

最短增益路径算法

也加先标记先扫描算法。其思想就是按照广度优先查找,用数量最少的边来生成增益路径。

时间复杂度:证明了增益路径的数量不会超过nm / 2,其中,n和m分别是顶点和边的数量。用邻接矩阵,广度优先算法求一条增益路径的时间属于O(n+m) = O(m),最短增益路径算法的时间效率属于O(nm 2 2 )。

伪代码——>

ShortestAugmentingPath(G)
//最短增益路径算法的实现
输入:网络G,具有一个源点1和一个汇点你,每条边(i,j)的容量都是正整数Uij
输出:最大流量X

对网络中的每条边(i,j),设Xij = 0
把源点标记为∞/-,再把源点加入到空队列Q中
while not Empty(Q) do
  i ← Front(Q); Dequeue(Q)
  for 从i到j的每条边 do //前向边
    if j没有被标记
      Rij ← Uij - Xij
      if Rij > 0
        lj ← min{li,Rij}; 用lj/i+来标记j
        Enqueue(Q,j)
  for 从j到i的每条边 do //后向边
    if j没有被标记
      if Xji > 0
        lj ← min{li,Xji}; 用lj/i-来标记j
        Enqueue(Q,j)
  if 汇点被标记了
    //沿着找到的增益路径进行增益
    j ← n //从汇点开始,用第二个标记反向移动
    while j ≠ 1 //没有到达源点
      if 顶点j的第二个标记是i+
        Xij ← xij + ln
      else //顶点j的第二个标记是i—
        Xji ← Xji -ln
    除了源点,擦去所有顶点的标记
    用源点对Q重新初始化
  return X  //当前的流量是最大的 

例子——>

这里写图片描述

补充

  • 网络中的最大流量值等于它最小割的容量(如:上例中的最小割是{(1,2),(4,3)},容量是3)
  • 所有已标记顶点到未标记顶点的边就构成了最小割
  • 如果从未标记顶点到已标记顶点的边,他们一定是空的(边上没有流量)
  • 预流算法的最坏时间复杂度可以达到O(nm)

参考:

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值