众所周知,网络流是探究网络上运输的一种图论分支。但是大多数人在第一次接触这个题时都有些畏惧感(比如说我),大佬可以自信跳过..


本文包括:

1.网络流的概念及基本性质

2.略谈 Edmonds-Karp增广路算法

3.详谈 Dinic 算法

4.网络流的应用以及ISAP算法引入


1 . 网络流的概念及基本性质

网络流是图论的一种重要分支,我们可以将网络流初步理解为一种 水道 一样的网络。

基本定义: (部分参考《算法竞赛进阶指南》)

对于一个网络 G = (V , E )G=(V,E) 为一张有向图,图中的每条有向边 ( X,Y)∉E(X,Y)∉E , 则 C(X,Y) = 0C(X,Y)=0 。图中还有两个节点 S , TS,T 十分特殊,我们将其称为 源点 和 汇点 。

我们将 ff 函数称作网络的流函数。

对于 (X,Y)∈E , f(X,Y)(X,Y)∈E,f(X,Y) 称为边的流量 , C(X,Y) - f(X,Y)C(X,Y)−f(X,Y) 称为边的剩余流量。

知道大佬们都不想看, 那么直接一点。

假设有一片有向的水域,有多条有向的河流,河流都从 SS 点出发,最终都汇向 TT 点。每条河流有一定的宽度,只允许最多不超过该条河流边权值 的水流通过。

如上图 ,蓝点为源点 , 红点为汇点。而紫色点和紫色边显然无用,选择不流过紫色。

默认 S 点的水量有无限多。

在初步了解后,按照流函数的定义,一个网络中的每条边实际上都有一条反向边,并且这些反向边都有一个负的流量, 这个定义将有助于我们解决之后的回溯问题。

基本性质:

1.容量限制

任意一条边的流量必定小于它的容量(及它的边权)。

2.斜对称定理

一条边 (X,Y)(X,Y) 中 XX 到 YY 的流量必定与其反边 (Y,X)(Y,X) 中 YY 到 XX 的流量相反。

3.流量守恒定理

除了源点 SS 和 汇点 TT 外 ,任意节点的 流入总量 都等于 流出总量 。即不会存储流量 。


2.略谈 Edmonds-Karp增广路算法

学习过匈牙利算法的同学已经了解增广路的定义,没有的话建议先 AA 掉P3386 【模板】二分图匹配 ,将有利于理解本文(貌似没有关联)。

但是增广路此时的定义为:

一条增广路从源点 SS 到汇点 TT 的路径上各边的剩余流量的最小值大于 0 。

而Edmonds-Karp增广路算法(下列简称EK算法)的思路就是对该网络进行BFS,不断找出其增广路,直至将该网络上的所有增广路全部找出。

EK算法的正确性显然,在这里就不给出详细证明。(有兴趣者可参考《算法竞赛进阶指南》)。

EK算法具体实现过程如下:

1 . 用BFS在网络上寻找可行增广路。

2 . 在BFS找到任意一条增广路时计算出该增广路上各边剩余流量的最小值 min 。

3 . 最大流 maxflowmaxflow 的值增加 min ,如此往复直至BFS找不增广路。

给出图 及 图的最大流 7 作参考

代码暂未上传。

但是EK算法存在明显的局限性,及每次更新都要从头到尾BFS一下,只能解决 O(nm^2)O(nm2) 的网络。

于是我们又有下面这个经一步优化的算法。


3.详谈 Dinic 算法

之所以详谈Dinic算法,是因为Dinic算法是代码较简单,较容易实现并且效率极高的网络流算法之一,它对于普通的网络图,处理范围可以达到 10^4 - 10^5104−105 。而相比之下,EK算法仅有 10^3 - 10^4103−104 的处理范围。

并且某位大师推演出Dinic算法在二分图中的复杂度仅有 m \sqrt{n}mn​ , 所以可以在二分图中愉快地跑网络流 啦。上一道例题P1129 [ZJOI2007]矩阵游戏,熟练后可以切了它。

我们先介绍一下Dinic算法的核心之一:残量网。

残量网是指在当前网络中的所有节点以及 剩余容量大于 00 的边构成的子图。

但是有了残量网还不够,要精准判断残量网上两点 X,YX,Y 的关系,即判断它们是否有环之类神奇的边,我们还要借助满足 d[y] = d[x] + 1d[y]=d[x]+1 的分层图。

Dinic算法思路:

1 . 开一个队列, 在残量网中BFS一次,按照遍历层数为每个点表上层次 d[ x ]d[x] ,构造分层图并且判断能否从源点 SS到达汇点 TT 。如果失败则说明残量网无法到达汇点。

2 . 在构造好的残量网上DFS寻找增广路并且,更新边及反边,(否则DFS无法后悔)。

3 . 不断重复 1 2 步骤直至构造的残量网无法到达汇点。

实践是检验真理的唯一标准

模板题P3376 【模板】网络最大流

AC 代码及讲解:

#include<bits/stdc++.h>
using namespace std; const int inf = 0x3f3f3f3 , N = + ; int head[ N* ], d[ N ] , to[ N** ] , w[ N** ] , next[ N** ] ; int n , m , s, t , tot = , maxflow = ;//maxflow记录答案 inline int read()
{
int s = ,w = ;
char g = getchar();
while(g<''||g>''){if(g=='-')w*=-;g = getchar();}
while(g>=''&&g<=''){s = s*+g-'';g = getchar();}
return s*w;
} queue<int> q ;//广搜时采用队列 void add( int x , int y , int z ){
tot++; to[ tot ] = y , w[ tot ] = z , next[ tot ] = head[ x ] , head[ x ] = tot;
tot++; to[ tot ] = x , w[ tot ] = , next[ tot ] = head[ y ] , head[ y ] = tot;
}//建立边和反向边,注意反向边的流量初始为 0 bool bfs(){//在残量网络上构造分层图
memset( d , , sizeof(d) ) ; //将之前的分层清0,继续跑残量网络找可行增广路
while( q.size() ) q.pop() ; //队列清 0 ;
q.push( s ) ; d[ s ] = ; //将源点加入队列,层数为 1 ,开始广搜
while( q.size() ){
int x = q.front() ; q.pop() ;
for( int i = head[ x ] ; i ; i = next[ i ])
if( w[ i ] && !d[ to[i] ] ){//目标边的流量不为0 且 为被遍历分层
q.push( to[ i ] ) ;
d[ to [ i ] ] = d[ x ] + ;
if( to[ i ] == t )return ; //找到一条可行增广路
}
}
return ;//未找到,不存在增广路
} int dinic( int x , int flow ){ //在分层图上进行增广
if( x == t )return flow ;//源点即使汇点,流量不限量
int rest = flow , k ;
for( int i = head[ x ] ; i && rest ; i = next[ i ] )//当前可流入最大流量不为0 ,
if( w[ i ] && d[ to [ i ] ] == d[ x ] + ){//目标路径有剩余流量,且不存在环之类神奇的东西
k = dinic( to[ i ] , min( rest , w[ i ] ) );//继续搜
if( !k )d[ to [ i ] ] = ; //剪枝,如果 k(下一层可流入流量图为 0 ),cut
w[ i ] -= k ;
w[ i ^ ] += k ;//占用k流量,注意反边要加上k,不然无法退回
rest -= k ; //当前节点的剩余汇入流量-k;
}
return flow - rest ; //递归完成
} int main()
{
n = read() ; m = read() ; s = read() ; t = read() ;
for( int i = ; i <= m ; ++i ){
int x = read() , y = read() , L = read() ;
add( x , y , L ) ;
}
int flow = ;
while( bfs() ){//存在增广路
while( flow = dinic ( s , inf ))maxflow += flow ;
}
printf("%d",maxflow) ;
return ;
}

Dinic算法一定要手敲一遍板子,不然你连错在哪都查不出来(除了机对)。


4.网络流的应用以及ISAP算法引入

ISAP算法是EK算法的另一类优化, ISAP算法只需一次BFS即可,但代码难度远远高于Dinic算法。

ISAP算法复杂度在非二分图上高于Dinic算法,在二分图则不如Dinic算法。

在此暂时不详讲,日后会更新ISAP算法详解。

网络流的应用

网络流应用较广, 但建议新手按以下顺序A题,熟练算法和增强应用能力。

网络流的应用

网络流应用较广, 但建议新手按以下顺序A题,熟练算法和增强应用能力。

P3376 【模板】网络最大流

U60438 及川奈砂的蛋糕

P1129 [ZJOI2007]矩阵游戏

P2891 [USACO07OPEN]吃饭Dining

感谢ssw大佬!!

网络流学习(转载自ssw 的博客)的更多相关文章

  1. 【转载】国内网站博客数据统计选免费Google Analytics还是百度统计

    [转载]国内网站博客数据统计选免费Google Analytics还是百度统计 Google Analytics谷歌统计是我用的第一个网站统计工具,当然现在也一直在用.Google Analytics ...

  2. React初步学习-利用React构建个人博客

    React初步学习-利用React构建个人博客 用React和Webpack写了一个很简单的个人博客,主要是想要熟悉一下react中各种基本基本属性及方法的使用.在构建过程中碰到不少问题,通过阅读官方 ...

  3. 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变

    转载来自朱小厮博客的 一文看懂Kafka消息格式的演变     ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...

  4. 如何快速转载CSDN中的博客

    看到一篇<如何快速转载CSDN中的博客>,介绍通过检查元素→复制html来实现快速转载博客的方法.不过,不知道是我没有领会其精神还是其他原因,测试结果为失败.

  5. Trie树(c++实现)——转载自jihite的博客

    Trie树(c++实现)   原理 先看个例子,存储字符串abc.ab.abm.abcde.pm可以利用以下方式存储 上边就是Trie树的基本原理:利用字串的公共前缀来节省存储空间,最大限度的减少无谓 ...

  6. JavaScript资源大全中文版(Awesome最新版--转载自张果老师博客)

    JavaScript资源大全中文版(Awesome最新版)   目录 前端MVC 框架和库 包管理器 加载器 打包工具 测试框架 框架 断言 覆盖率 运行器 QA 工具 基于 Node 的 CMS 框 ...

  7. 学习Python不得不关注和学习的国外大神博客

    注意 : 本文收集于网路 . 由于常常更新 , 有些链接打不开, 请自备梯子 在学习Python过程中,总会遇到各种各样的坑, 虽然Python是一门优美而简单易学的语言 . 但当学习后 , 总想着更 ...

  8. [转]如何快速转载CSDN中的博客

    原文:https://blog.csdn.net/bolu1234/article/details/51867099 前言   对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提高,有时 ...

  9. iOS开发学习之大牛们的博客

    http://blog.csdn.net/iosbird/article/details/51981023 唐巧:http://blog.devtang.com/blog/archives/ 王巍:h ...

随机推荐

  1. Android屏幕适配和方案【整理】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这里只是根据参考资料整理下,具体内容请阅读参考资料. 原型设计图 推荐1倍效果图,即采用 720 * 360 大小( 1280 *7 ...

  2. 学习ASP.NET Core Razor 编程系列十八——并发解决方案

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  3. dubbo不完全指南

    Dubbo架构 节点角色说明 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的 ...

  4. python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍

    目录 python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍.md 一丶字典 1.字典的定义 2.字典的使用. 3.字典的常用方法. python学习第八讲,python ...

  5. C# net request payload形式发送post请求

    因为开发微信群发电脑版需要模拟微信POST请求,微信发送消息使用request payload发送,实际发送的是json字符串.我们只需要生成的json字符串和请求的一致,header头完全模拟即可. ...

  6. chrome主页被篡改为hao123 win10系统

    应该是开了个从流氓网站下的蓝灯,然后发现主页被篡改 尝试chrome设置修改无效,应该是快捷方式被改了 系统 win10 1.打开对应的下面两个地址,找到chrome的快捷方式,右键属性 C:\Use ...

  7. C#面向对象(1)

    一.面向对象(OOP) 面向过程 面向过程就是分析出解决问题的所需要的步骤,然后每个步骤使用函数实现,使用时将函数依次调用即可 C语言 面向对象 对象:生活中真实存在的事物(电脑.手机.草.树.... ...

  8. Spring入门(一):创建Spring项目

    本篇博客作为Spring入门系列的第一篇博客,不会讲解什么是Spring以及Spring的发展史这些太理论的东西,主要讲解下如何使用IntelliJ IDEA创建第一个Spring项目以及通过一个示例 ...

  9. HeadFirst设计模式读书笔记之工厂模式

    1. 简单工厂 1. 你开了一家披萨店,点披萨的方法可能是这样: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals ...

  10. 【20190220】HTTP-知识点整理:TCP/IP与HTTP

    TCP/IP是互联网相关的各类协议族的总称,HTTP属于它内部的一个子集. 一.TCP/TP的分层管理 1. 应用层 应用层决定了向用户提供应用服务时通信的活动.TCP/IP 协议族内预存了各类通用的 ...