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


本文包括:

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. Java~时间戳小知识

    大叔对java时间戳使用的总结 Java里的Date对象有方法setTime,主要是将一个时间戳转成一个日期对象,而这个时间戳的标准是unix标准,即当前时间与1970/1/1相差的毫秒数,记得是毫秒 ...

  2. ASP.NET Core开发者指南

    ASP.NET Core开发者指南 2019年ASP.NET Core开发者指南: 你可以在下面找到一张图,该图展示了你可以选取的路径及你想学习的库,从而成为一名 ASP.NET Core 开发者.“ ...

  3. Django-restframework之路由控制、解析器及响应器

    django-restframework之路由控制.解析器及响应器 一 前言 本篇博客介绍 restframework 框架的剩下几个组件,路由控制有三种:传统路由.半自动路由及全自动路由:解析器是用 ...

  4. PHP设计模式的六大设计原则

    PHP设计模式的六大设计原则 1 简介 软件设计最大的难题就是应对需求的变化,但是纷繁复杂的需求变化却是不可预料的.此时,我们可以通过六大设计原则良好的应对未来的变化. 2 讲解 2.1 单一职责原则 ...

  5. 获取url特定参数

    获取通过url拼接的特定参数值: // 获取url指定参数 function getUrlParams(name) { var reg = new RegExp("(^|&)&quo ...

  6. 【代码笔记】Web-CSS-CSS Align

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  7. HTML页面转换为Sharepoint母版页(实战)

    分享人:广州华软 极简 一. 前言 SharePoint有母版页.布局页.母版页存放着如头部(顶部菜单.导航),底部等比较通用部分,通常网站只需一套即可:而布局页,则存放着主要内容部分,根据页面需要, ...

  8. ios View 向上拉界面源码

    如下的资料是关于ios View 向上拉界面的代码. #pragma mark - 上升效果- (void)ToUpSide {          } - (void)moveToUpSide {   ...

  9. ORA-04030: out of process memory when trying to allocate 152 bytes (Logminer LCR c,krvtadc)

    今天使用LogMiner找回误更新的数据时,查询v$logmnr_contents时,遇到了"ORA-04030: out of process memory when trying to ...

  10. docker部署postgresql时,data目录不生效的问题探究

    今天用docker部署postgresql,用的是官方的镜像.结果挂载完 /var/lib/postgresql/data目录后,和容器里的目录其实并没有挂载成功. 母机上的目录并没有成功挂载到容器里 ...