Network Flows 基础

浅谈\(Network-flows\)基础

网络流基础知识以及解法

网络流在OI中是显得尤为重要的。在《算法导论》中就用了\(35\)页来讲述网络流的知识,在这里,我来给大家讲一讲网络流的一些基础知识。

如果说网络流很难,那么你就大错特错。建议学完最短路,最小生成树或者LCA,tarjan的\(2\)种应用后就可以来看一眼。一般普及组就能消化。

\(Flow\)

首先我们要认识流量是什么。我们知道,我们城市中的每一条路肯定有一定的宽度,而这些宽度就限定了车辆。(我们也可以把红绿灯两端看为一条路的长度)

网络流就对诠释上了这么一个值,它不同于最短路。\(a\)站向\(b\)站有一条流量为
5的路,那么你就只能通过5辆(或者是其它单位)车,而且通过以后就无法再通过。我们也就可以推出几个东西:

\(I.\)我们可以先通\(n\)辆车,再通\(m\)辆车。(\(n+m<=\)这条路的\(flow\))

\(II.\)如果我们从\(a\)站到\(b\)站只剩\(20\)\(flow\),那么我们有一条\(flow\)\(15\)的边连接\(b\)\(c\)。我们很快能推出\(a\)\(c\)只有15的\(flow\)。(因为后者限制了前者)

\(Max\ flow\)

先认识一下\(S\)(\(source\))和\(T\)(\(sink\))的概念。\(S\)就是常说的源点,\(T\)就是汇点(也就是起点和重点,这个跟最短路的概念是一样的)。我们有一张图,要求从源点流向汇点的最大流量(可以有很多条路到达汇点),就是我们的最大流问题(\(max\ flow\))。(一般源点是无限流量的)

然后我们来认识一下增广路(注意路不是边),就是说,从源点到汇点,只要有\(flow\)(\(flow>0\))流过去,这条路就是增广路。在一些最大流算法中,就是将这些路增广(意思就是走掉这条路,带走的\(flow\)肯定就是这条路的\(min flow\)),如图:

2262.png

我们从\(4\)\(3\),肯定可以先从\(flow\)\(20\)的这条边先走。那么这条边就被走掉了,不能再选,总的\(flow\)\(20\)(现在)。然后我们可以这样选择:

\(I.\) \(4->2->3\) 这条增广路的总\(flow\)\(20\)。到\(2\)的时候还是\(30\),到
\(3\)了就只有\(20\)了。

\(II.\) \(4->2->1->3\) 这样子我们就很好的保留了\(30\)\(flow\)

所以我们这张图的\(max\ flow\)就应该是\(20+30=50\)

求最大流是很简单的,稍后我们会讲解求最大流的\(3\)种方法。

\(Minimum\ cost\ Maximum\ flow\) \((MCMF)\)

这也是耳熟能闻的费用流——最小费用最大流(\(Minimum\ cost\ Maximum\ flow\))。我们给予这张图一个费用值(也就是最短路问题),然后在求出最大流的基础上,把最小费用的路径求出来。这个难度就上升到了提高组的难度,并不是大家都可以先决的。(不过还是很简单)

\(Max\ flow\) 解法锦集

\(Code\)(所有)请看:剪贴板

\(Edmond-Karp\) 动能算法 (\(EK\)算法)

这个算法很简单,就是Dfs找增广路,然后对其进行增广。你可能会问,怎么找?怎么增广?

\(I.\)找?我们就从源点一直Dfs走来走去,碰到汇点就停,然后增广(每一条路都要增广)。我们在Dfs的时候就注意一下\(flow\)合不合法就可以了。

\(II.\)增广?其实就是按照我们找的增广路在重新走一遍。走的时候把这条路的\(min\ flow\)减一减,然后把\(Answer\)加上\(min\ flow\)就可以了。

再讲一下反向边。增广的时候要注意建造反向边,原因是这条路不一定是最优的,这样子程序可以进行反悔。假如我们对这条路进行增广了,那么其中的每一条边的反向边的\(flow\)就是它的\(flow\)

20473.png

讲一下一些小细节。如果你是用邻接矩阵的话,反向边直接就是从\(table[x,y]\)变成\(table[y,x]\)。如果是常用的链式前向星,那么在加入边的时候就要先加入反向边。那么在用的时候呢,我们直接\(i\ xor\ 1\)就可以了(\(i\)为边的编号)。为什么呢?相信大家都是知道\(xor\)的,那么我们在加入正向边后加入反向边,就是靠近的,所以可以使用\(xor\)。我们还要注意一开始的编号要设置为\(tot=1\),因为边要从编号\(2\)开始,这样子\(xor\)对编号\(2,3\)的边才有效果。

\(Dinic\)

我们知道,一条路一条路找是十分的慢的,我们就设想可不可以很多条路一起找。答案当然是可以的。我们只需要一个问题,这些路是同时找的,如果有些路很调皮,往回(别的路)找,那么别的路不就是异常尴尬。

我们给这张图每一条边都指定一个方向,就不会出现上述情况。这时候我们就可以知道分层这个概念。我们对于每一次增广以后的图,给它进行分层。我们规定,低的级别只能去高的级别的点(而且只能高\(1\)级别)。而级别就是它与源点的距离。我们对于每一次整体增广来一次\(BFS\)就可以了。

\(ISAP\)

这个是\(SAP\)算法的加强版(\(Improved\))。建议去看一下\(permui's\ blog\),也可以看我的。这里不做讲解。

\(Minimum\ cost\ Maximum\ flow\) \((MCMF)\) 解法

好的我承认我只会\(EK+SPFA\),直接看\(Code\)。很简单,网络流套一套\(SPFA\)。我相信,天下没有多少人可以卡掉\(EK+SPFA\)(但是的确有很多)。

这里推荐一下原始对偶算法(网上没有多少人讲)和zkw费用流算法(zkw太强了!)。博主正在学习中。

网络流基础知识拓展

前面都看懂的同学可以看一下以下内容。

\(Min\ cut\)

割其实就是删边的意思,当然最小割就是割掉\(X\)条边来让\(S\)\(T\)不互通。我们要求\(X\)条边加起来的流量综合最小。这就是最小割问题。

其中我们要认识一个定理: 最小割=最大流 (虽然我并不会证明)

二分图匹配

这个就尤为简单,可以用匈牙利这种水法。这里不多讲,还是参考我的博客

建模

在会了最大流和费用流后,建模显得尤为重要。就像\(JZOI\)狼与羊的故事,就是一个例子。

前期遇到这种题目,暴搜?神奇\(BFS\)?错误。我们首先要考虑一下会不会有二分图匹配,最小割的模型(一般不会有普通的最大流)。然后建立(超级)源点和(超级)汇点。什么意思?就是当很多个源点和很多个汇点的时候,我们就可以用超级源点和超级汇点代替"源点"和"汇点"的位置(也就是把超级源点连向各个源点.超级汇点连向各个汇点,方向按题意来定)。

这是最常见的建模的方法之一,也是做二分图匹配的方法。还有很多建模方法,等大家去自己研究。这里有一篇好的博客,供大家自己研究。

来一道题练练手:\(T\)

转载于:https://www.cnblogs.com/FibonacciHeap/articles/9691400.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值