zoukankan      html  css  js  c++  java
  • 深谈网络流

    网络流 目前 在我看来只有最大流 最小割 费用流 这几种模型其依赖的其实都是反向流能反悔的原因,每次都是找到最短或者费用最小的流进行增广直至不能再增广下去。

    基于这样的思想 也就解释了费用流可以代替KM算法在二分图的带权匹配之中的正确性。

    最大流等于最小割 这无疑是正确的 但是注意 割边的集合并非所有满流的边而所有满流的边也不一定就是割边。

    通常我们这样判断割边 从源点出发 然后能到的点到不能到的点之间组成一组割集 注意 只是一组 我认为还有多组,至于一些毒瘤的题目让输出方案 用的也不是一些网络流的高级做法如预流推进什么的,此时应该这样来做。因为割边之后可能还会出现割边 也就是可能同属一个方案什么的,全部要求输出方案的话我的建议是 删边然后跑最大流判断最大流小了没有如果小了和当前的边的权值一样说明其存在方案之中,

    也正是因为这样 导致我一道题目调了很久。。

    对于一些普通网络流的题 最常见的无疑是dinic 和EK 。

    这两种算法足以关键是建模问题:

    1 有交叉建模问题 如酒店之王P1402 这道题是一个交叉建模问题 人对应菜 人对应房间 当时我想的是人对应菜那么人向菜连边然后人对应房间 那么人向房间连边 这样是满足不了题目要求的 那么就菜向房间连边。当然事实证明这个有一定的错误 因为每个人对应的房间不同而对应相同的菜的话 那么这个菜对应的房间就不同跑不了。改变思路是 菜向人连边 而 人向 房间连边。显然形成了一个线性的关系,注意由于人只能使用一次,所以人应该拆点 形成一条流量为1的边表示只能有一次机会经过其。而菜和房间由源点和汇点保证 这样求最大流无疑是最大匹配。

    2 最大流换最小割的模型。,如小M的作物P1361,很有意思的题目。考验的是转换模型,将收益为A的连向源点 收益为B的连向汇点 组合收益就各自有各自的源点出发连向作物,这样做的原因 我在最小割的时候割掉的边一旦是农作物组合中其中的一个连向源点的那条边的时候此时这个组合也必然被割掉因为他们是连在一起的。考虑到这样的模型 我们发现求完最小割 那么此图就不再联通 于是乎剩下的边就是我们的收益。

    3 二分图匹配的模型。其实就是用dinic做匈牙利的二分图最大匹配,当然可能没有匈牙利要快但是好像也差不到哪去。关键这样做的正确性 不需要拆点因为源点和汇点的流量已经限制过了。为什么能求出最大匹配因为有反向流这种东西 我可以返回原本的局面然后再次寻找流。这就是正确的原因一直寻找增广路。

    4 动态建图模型。这种模型很少见 P2765 魔术球问题这道题就是一个动态建边不断寻找增广路,题目中询问的是n个柱子最多能放多少个球,我们也不知道能放多少个。二分好像可以但是处理每个球能放到其他球上的时候不好处理了 因为我们要求一个球放在另一个 球上面当且仅当这个球已经放上去了 也就是说此球是合法的,这才能放,所以是一个球一个球放,因为每次只能在某个柱子上放球所以每次轮到某个球放的时候其他球无疑已经放上去了当然 有两种决策 一个放到新的柱子上此时需要一个中间点限制其柱子的数量也就是直接放到柱子数不能超过n 那么我们把T1连向T容量为n即可。至于能放到其他柱子上的球 连边放上去就好了因为此时其他柱子一定已经全部合法了,这样去跑最大流就好了 ,建图是动态的。

    4 路径覆盖模型求出一个DAG不相交的路径的最小覆盖,这里 转模型的时候 过程是这样的的 不想交的路径覆盖 定义一个点也算一个路径覆盖那么基础的路径覆盖为n每有两个点连起来形成一条路径的覆盖说明答案减少1既然答案会减少1何不如让答案一直减少下去 但是是不想交的 如果两点之间练过线了那么此时其中的一个点就不能再和其他点连边,我们要寻找的就是能连边多少次连边一次意味着答案将会减少1 那么最终的答案就是n也就是顶点的个数-匹配的次数。

    5 二分+最大流的判定 有些题目让求最多的答案我们知道答案的上下界且不好求的时候可以采用二分+最大流判定答案 如p3153类型的题目我们不知道要放多少次音乐,如果我们一开始就放出最大的流量的话无法保证一些人确实流到了这个最大的流量,而二分出一个答案然后最大流判定的话这个效果是最好的,况且我们也知道了答案的上下界不像魔术球那道题不知道上界。

    6 分层图问题,一般来说唯一的一条流在分层图上跑最小费用最大流和在分层图上跑dij是等效的。如汽车行驶问题,dij完全可跑当然也可建图跑费用流。

    7当然还有二分图的最大独立集问题 转化的模型为 n-最小点的覆盖 最小点覆盖==最大匹配==最大流。

    8 一面对多面的模型我们知道网络流中流为1时是只能输送流量1 但是假如这一条流能对好多个点进行贡献呢,此时就是一流对多点的模型了。例如P2980 其一流对应的是多个点 我们想办法让这一流贯穿所有的点 由于这些点事连续的我们可以将其连上线那么一流从s 到 t流过就说明了一流对多点,如何限制人数呢?想一下我们这条流是很有用的限制的话可以加在点与点之间,从一个点到另一个点表示限制,S到第一个点为INF 表示原本的流量是INF 然后经过第一个点的限制流量少了 这些流量可以通过代价来换取,最后只要跑出最大流那就是答案。很巧妙的建模。

    9 拆点转费用流问题 P2053 接近于线性规划问题一般来说用费用流解决最小费用最大流是非常好用的东西,这道题就是对每个工程师单独思考发现对于这个人要修的车子 W1*k-1+W2+k-2+...拆点跑费用流即可。看看放在哪个位置最合适 其实也就是一个带权二分图的匹配,注意这里并不是完备匹配 KM算法并不适用。

    10 分层图网络流 发现是必要的真的出现了多流量的分层图 一般都是要网络流跑的可以限制流量 而dij则跑不了的 如果不知道要放多少层 可以二分。分层图网络流如1999 这个分层图跑的妙啊。看来有这种问题的都需要转换成分层图的模型。不断扩充图 当然这上界并不明确。当然范围不大的话二分和枚举都可以。

    11 造点 有些题目中并没有给出明确点提供使用此时应该自己造出来点放到网络上。P2825 此题是...显然没有明确的点供使用当然也不是一张二分图,黑白染色行不通我们发现白点和白点也会冲突,那么此时观察一个合法的炸弹放的位置他需要一行和一列 那么也就是说每有一个合法的炸弹 此时付出的是某一行和某一列,把两个能凑成炸弹的行列连边跑最大流即可。构造一波点。

    暂时就这么多了,学学看看吧。

    update : 当前弧优化还没有说呢 以前一直写朴素的dinic的我也是醉了...复杂度极其不科学 或者说加上当前弧优化dinic才是真正的dinic 可以跑的非常的快。

    做法:每次dfs扩流的时候记录哪一条边被扩增了一个比较浅显的想法是增广后的边不会再被增广考虑一下这个命题的正确性.

    初看这个结论可能很多人都会觉得非常的显然 的确这个命题很容易被想到 一个被增广过的路也就是完全增广的路是不可能再被增广了。可思考一种情况 这条增广的路如果被缩小了呢?它仍然具有被增广的空间,一条增广路很容易被缩小 反向边可能使其再次缩小,此时这条边已经被我们删掉了 但是这条路真的不可能再增广了么,通过画图可以发现答案的确如此。在论证之前还有一个小性质和终点相连的边一旦被增广就不可能再被缩小 因为到终点就停止没有跑反向边的性质 考虑一条增光路被增广之后再被缩小 再次增广其的必要条件正向的跑这条边是可以跑 但是接下来是它是无法到达汇点的 它到汇点的路上至少有一条边是满的 因为如果不是满的在刚才跑反向边的时候其实没有必要跑反向边一旦跑了反向边就说明这个点是到不了终点的所以跑向了反向边。所以刚才它到汇点的路上至少有一条边是满的,那么这条边还是不可增广的。还有一些情况诸如这条边还可以通向其他边 分两种情况正向边 但是到不了终点那种,或者就是反向边。。。当你看到这个地方 你会发现博主是个sb...

    以上纯属瞎bb 我理解错弧优化了...以为满的边在接下来的任何时刻都不需要了,其实不然...还需要 这个优化只是基于当前dfs的优化我以为是基于dfs和bfs的优化导致思考了很久觉得这个东西是错的。

    但是基于dfs的优化的话就很显然了 没有流量的边自然再接下增广的时候没有任何的价值,所以暂时性的删掉就好了 bfs的时候再加上去。

  • 相关阅读:
    windows系统pycharm终端更改为git bash
    python 连接mysql数据库操作
    selenium 鼠标,键盘操作
    selenium定位,操作元素
    python读取csv,Excel,Txt,Yaml 文件
    Jmeter 学习 搭建(1)
    接口测试
    UnitTest+HTMLTestRunner实战
    HTMLTestRunner.py 文件,已修改完成
    UnitTest + HTMLTestRunner
  • 原文地址:https://www.cnblogs.com/chdy/p/11049552.html
Copyright © 2011-2022 走看看