zoukankan      html  css  js  c++  java
  • 上下界网络流

    上下界网络流

    0x00 前言

    • 这又是一个大坑,有必要填上,学会了可以暴力建图,省去一些繁琐的构思

    0x01 什么是上下界网络流

    • 这里我们把网络流分为几种情况:有无源汇,只要求可行或最大或最小,有无费用,是否有下界
    • 有源汇网络流:除了一个S(源)流出量没有限制和一个T(汇)流入量没有限制,其他节点必须满足流量守恒
    • 无源汇网络流:所有点都必须满足流量守恒
    • 可行流:是否存在一种流量的方案似的网络流满足流量守恒的条件
    • 最大流:满足流量守恒条件下最大的流量,最小流类似
    • 费用流:满足一定条件(最大流,最小流)下费用最大或最小
    • 普通的网络流有一个上界,即每条边最多流量是给定的。上下界网络流同时给出了下界,即一些边的流量要求至少为一个值
    • 显然可行流总是得和上下界放在一起,不然一个流量为0的方案总是可行的
    • 上下界网络流一般用于求解各种有上下界网络流问题(废话)

    0x02 做一些定义

    • N:整个网络
    • p:一个节点
    • e:一条边
    • S:源
    • T:汇
    • low_in[p],low_out[p]:p的下界流入和流出量(所有入边流量的下界和,所有出边流量的下界和)
    • free_in[p],free_out[p]:p除了下界流量之外的流入和流出量
    • lower[e],upper[e]:e的下界和上界
    • SS:超级源
    • TT:超级汇

    0x03 从最简单的开始——无源汇可行流

    • 假设这个网络叫N
    • 上界的问题我们是身经百战,见得多了,但是下界没怎么碰到过
    • 但是为什么从无源汇开始呢?不是有源汇的问题我们更熟悉么?
    • 你要是问我能不能在有下界的图里直接增广,那我明确地告诉你:你们这样是不行的。
    • 不管是dinic,最高标什么乱七八糟的网络流算法都无法求解有下界的网络流
    • 我们只能考虑对图做一些变换,把下界去掉
    • 显然的一种想法是先给条边强制流上lower[e]的流量,剩下upper[e]-lower[e]的流量是自由的,即让每条边的流量变为new_lower[e]=0,new_upper[e]=upper[e]-lower[e],我们把这个改过的网络叫做N'
    • 想法很显然,正确性也很显然,是错的
    • 为什么呢?因为这么一搞不能保证流量守恒了。
    • 我们考虑这点p流量守恒的表达式
    • low_in[p]+free_in[p]=low_out[p]+free_out[p]
    • 事实上我们把low_in,low_out这部分删去了,这会导致流量不平衡
    • 这并不难解决,我们新建SS和TT,对于每一条边<u,v>,下界为lower,我们拆成从SS向v连容量为lower的边,从u向TT连容量为lower的边
    • 这易于理解,我们相当于把lower这一部分拆了出去
    • 然后对N作上文所提到的变形
    • 这里有一个简单的小优化,重新考虑p流量守恒的表达式
    • low_in[p]+free_in[p]=low_out[p]+free_out[p]
    • 稍作变形
    • low_in[p]-low_out[p]=free_out[p]-free_in[p]
    • 如果令 dlt=low_in[p]-low_out[p]
    • 发现如果在N'中求出了一个可行流,p这个点在N中实际的流出比流入要多了dlt(假设dlt为正,负一会考虑)
    • 从SS向p连一条流量为dlt的边。
    • 如果dlt为负呢?说明这个点流入比流出多了,从这个点向TT连一条流量为-dlt的边
    • 这相当于把原来的一些SS-p-TT的边合并了,减少了边的总数,容易得到这两个图的性质是等价的。
    • 变形完后,从SS向TT做一次有源汇最大流,如果SS所有的流出边都满流,那么可行流就存在
    • 为什么?
    • 首先容易发现如果SS流出的边都满流了,那么流入TT的边肯定也都满流了(这两部分总流量是一样的,原因可以考虑N中一条边的下界对N'的影响)
    • 考虑我们建图的过程,如果SS所有的流出边都满流了,那么说明:
    1. 下界都被满足了
    2. 所有点都满足流量守恒
    • 好了呀,你还要怎么样嘛,这不就是我们要求的东西么
    • 最后每条边的实际流量就是它的反向边流量加上 下界流量

    0x04 无源汇最大/最小流

    • 给每条边加一个1的费用
    • 用下面提到的无源汇上下界费用流做

    0x05 有源汇最大流

    • 这妙极了,看到这的读者不妨先自行思考一番,我们能否套用刚才求解无源汇可行流的方法?
    • 我们给T->S加一条容量为[0,INF]的边E!
    • 这样就变回了一个求解可行流问题,做一遍可行流
    • 此时E的流量就是S->T的当前流量C1(考虑一下为什么),但是C1不一定是最大流,简单想个例子就可以得出这个结论
    • 我们把E删去,再在N'的残量网络中做一次从S到T的增广(不是SS到TT!),设增广的流量为C2,总的最大流就是C1+C2,由于在残量网络中增广不改变流量守恒性质,这个算法的正确性是显然的

    0x06 有源汇……最小流?

    • 有了下界就有了求最小流的坑爹问题
    • 有个显然的想法,先加T->S的INF边求可行流C1,然后C1是不是最小流呢?
    • 并不是,这里请读者自行举例以加深对此的理解,给个提示:考虑图中的成环流量
    • 然而我们可以在残量网络中退流
    • 把INF边删了,从T向S跑一遍最大流,流量为C2,C1-C2即为最小流
    • 正确性和上面一样啦

    0x07 无源汇费用流!

    • 老样子,先求一个可行流?
    • 这里构图的时候遇到了点麻烦,边有费用,而且费用不一样,如果用优化版的构图方法无法合并一个点的出边和入边
    • 只好每条边都拆成单独的两条边了
    • 每条边的费用呢?费用会被算两次耶?选一条边加费用咯,任性,我喜欢选SS到v的边
    • 然后直接从SS到TT跑费用流即可。
    • 事实上我还YY了一个愚蠢的方法,有兴趣的读者可以尝试一下
    • 先在图中求一个可行流,然后运用消圈算法优化答案
    • 消圈算法:用spfa在图中找负/正环
    • 推荐做一下bzoj3876支线剧情,codevs上的支线剧情真坑爹,时限只有2s,相比之下bzoj有10s
    许愿弥生改二
  • 相关阅读:
    layui第三方组件运用
    layui select lay-filter就不渲染和全局渲染用法和校验
    layui 点击操作列后背景色去掉
    layui混合案列问题
    使用layui富文本添加日志内容,并获取子窗体的富文本内容
    layu tab切换table
    layui 父窗体传子窗体select动态选中
    jstl过长的内容处理空格以及换行并通过js处理内容自动换行
    js中运用jstl标签解决checked是否选中等问题
    javaMD5实现加密解密
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6745524.html
Copyright © 2011-2022 走看看