• 【教程】上下界网络流建模方法总结


    前言

      之前学习上下界网络流的时候,花了很多时间去理解建模的方式和原理,然而今天复习的时候发现忘得差不多了QwQ。于是参考了一下以前的代码,再次做了个总结,放在博客里,省得以后忘掉QwQ。


    无源汇可行流

      建模方法:

      首先建立一个源$ss$和一个汇$tt$,一般称为附加源和附加汇。

      对于图中的每条弧$<u,v>$,假设它容量上界为$c$,下界$b$,那么把这条边拆为三条只有上界的弧。

      一条为$<ss,v>$,容量为$b$;

      一条为$<u,tt>$,容量为$b$;

      一条为$<u,v>$,容量为$c-b$。

      其中前两条弧一般称为附加弧。

      然后对这张图跑最大流,以$ss$为源,以$tt$为汇,如果所有的附加弧都满流,则原图有可行流。

      这时,每条非附加弧的流量加上它的容量下界,就是原图中这条弧应该有的流量。

      理解方法:

      对于原图中的每条弧,我们把$c-b$称为它的自由流量,意思就是只要它流满了下界,这些流多少都没问题。

      既然如此,对于每条弧$<u,v>$,我们强制给$v$提供$b$单位的流量,并且强制从$u$那里拿走$b$单位的流量,这一步对应着两条附加弧。

      如果这一系列强制操作能完成的话,也就是有一组可行流了。

      注意:这张图的最大流只是对应着原图的一组可行流,而不是原图的最大或最小流。


    有源汇可行流

      建模方法:

      建立弧$<t,s>$,容量下界为$0$,上界为$infty$。

      然后对这个新图(实际上只是比原图多了一条边)按照无源汇可行流的方法建模,如果所有附加弧满流,则存在可行流。

      求原图中每条边对应的实际流量的方法,同无源汇可行流,只是忽略掉弧$<t,s>$就好。

      而且这时候弧$<t,s>$的流量就是原图的总流量。

      理解方法:

      有源汇相比无源汇的不同就在于,源和汇是不满足流量平衡的,那么连接$<t,s>$之后,源和汇也满足了流量平衡,就可以直接按照无源汇的方式建模。

      注意:这张图的最大流只是对应着原图的一组可行流,而不是原图的最大或最小流。


    有源汇最大流

      建模方法:

      首先按照有源汇可行流的方法建模,如果不存在可行流,更别提什么最大流了。

      如果存在可行流,那么在运行过有源汇可行流的图上(就是已经存在流量的那张图,流量不要清零),跑一遍从$s$到$t$的最大流(这里的$s$和$t$是原图的源和汇,不是附加源和附加汇),就是原图的最大流。

      理解方法:

      为什么要在那个已经有了流量的图上跑最大流?因为那张图保证了每条弧的容量下界,在这张图上跑最大流,实际上就是在容量下界全部满足的前提下尽量多得获得“自由流量”。

      注意,在这张已经存在流量的图上,弧$<t,s>$也是存在流量的,千万不要忽略这条弧。因为它的相反弧$<s,t>$的流量为$<t,s>$的流量的相反数,且$<s,t>$的容量为0,所以这部分的流量也是会被算上的。


    有源汇最小流

      有源汇最小流的常见建模方法比较多,我就只说我常用的一种。

      建模方法:

      首先按照有源汇可行流的方法建模,但是不要建立$<t,s>$这条弧

      然后在这个图上,跑从附加源$ss$到附加汇$tt$的最大流。

      这时候再添加弧$<t,s>$,下界为$0$,上界为$infty$。

      在现在的这张图上,从$ss$到$tt$的最大流,就是原图的最小流。

      理解方法:

      我们前面提到过,有源汇可行流的流量只是对应一组可行流,并不是最大或者最小流。

      并且在跑完有源汇可行流之后,弧$<t,s>$的流量就是原图的流量。

      从这个角度入手,我们想让弧$<t,s>$的流量尽量小,就要尽量多的消耗掉那些“本来不需要经过$<t,s>$”的流量。

      于是我们在添加$<t,s>$之前,跑一遍从$ss$到$tt$的最大流,就能尽量多的消耗那些流量啦QwQ。


    总结

      口胡完毕。

      我姿势水平不高,没见过什么上下界网络流的题(或许真的不常考?),唯一见过的一道就放上来叭QwQ。

    题目与题解

      Inspection LA 4597 NEERC 2009

      题解还请看我的博客QwQ:http://www.cnblogs.com/mlystdcall/p/6734979.html

  • 相关阅读:
    [Effective C++ --009]确定对象被使用前已先被初始化
    [Effective C++ --008]别让异常逃离析构函数
    [Effective C++ --007]为多态基类声明virtual析构函数
    [Effective C++ --006]若不能使用编译器自动生成的函数,就该明确拒绝
    [Effective C++ --005]了解C++默默编写并调用哪些函数
    [000]socket通信--server和client实现的简单例子
    [014]模板-模板实参推导
    [013]模板-非类型模板参数
    [012]泛型--lambda表达式捕获
    U3d keyCode值对应的按键
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/6734852.html
Copyright © 2020-2023  润新知