网络流学习(转载自ssw 的博客)
众所周知,网络流是探究网络上运输的一种图论分支。但是大多数人在第一次接触这个题时都有些畏惧感(比如说我),大佬可以自信跳过..
本文包括:
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 = 10000 + 19 ;int head[ N*2 ], d[ N ] , to[ N*10*2 ] , w[ N*10*2 ] , next[ N*10*2 ] ;int n , m , s, t , tot = 1 , maxflow = 0 ;//maxflow记录答案 inline int read() {int s = 0,w = 1;char g = getchar();while(g<'0'||g>'9'){if(g=='-')w*=-1;g = getchar();}while(g>='0'&&g<='9'){s = s*10+g-'0';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 ] = 0 , next[ tot ] = head[ y ] , head[ y ] = tot; }//建立边和反向边,注意反向边的流量初始为 0 bool bfs(){//在残量网络上构造分层图memset( d , 0 , sizeof(d) ) ; //将之前的分层清0,继续跑残量网络找可行增广路while( q.size() ) q.pop() ; //队列清 0 ;q.push( s ) ; d[ s ] = 1 ; //将源点加入队列,层数为 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 ] + 1;if( to[ i ] == t )return 1 ; //找到一条可行增广路 }}return 0 ;//未找到,不存在增广路 }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 ] + 1 ){//目标路径有剩余流量,且不存在环之类神奇的东西k = dinic( to[ i ] , min( rest , w[ i ] ) );//继续搜if( !k )d[ to [ i ] ] = 0 ; //剪枝,如果 k(下一层可流入流量图为 0 ),cutw[ i ] -= k ; w[ i ^ 1 ] += k ;//占用k流量,注意反边要加上k,不然无法退回rest -= k ; //当前节点的剩余汇入流量-k; }return flow - rest ; //递归完成 }int main() {n = read() ; m = read() ; s = read() ; t = read() ;for( int i = 1 ; i <= m ; ++i ){int x = read() , y = read() , L = read() ;add( x , y , L ) ; }int flow = 0 ; while( bfs() ){//存在增广路while( flow = dinic ( s , inf ))maxflow += flow ; }printf("%d",maxflow) ;return 0 ; }
Dinic算法一定要手敲一遍板子,不然你连错在哪都查不出来(除了机对)。
4.网络流的应用以及ISAP算法引入
ISAP算法是EK算法的另一类优化, ISAP算法只需一次BFS即可,但代码难度远远高于Dinic算法。
ISAP算法复杂度在非二分图上高于Dinic算法,在二分图则不如Dinic算法。
在此暂时不详讲,日后会更新ISAP算法详解。
网络流的应用
网络流应用较广, 但建议新手按以下顺序A题,熟练算法和增强应用能力。
网络流的应用
网络流应用较广, 但建议新手按以下顺序A题,熟练算法和增强应用能力。
P3376 【模板】网络最大流
U60438 及川奈砂的蛋糕
P1129 [ZJOI2007]矩阵游戏
P2891 [USACO07OPEN]吃饭Dining
感谢ssw大佬!!
转载于:https://www.cnblogs.com/LJB666/p/10665058.html
网络流学习(转载自ssw 的博客)相关推荐
- 蛙蛙推荐:一个程序员2012年技术学习总结 - 蛙蛙王子 - 博客园
蛙蛙推荐:一个程序员2012年技术学习总结 - 蛙蛙王子 - 博客园 蛙蛙推荐:一个程序员2012年技术学习总结 - 蛙蛙王子 - 博客园 俗一吧,也总结一下,程序员,代码说话. posted on ...
- 如何快速转载别人的CSDN博客文章并附带格式与图片
1.问题背景 最近在学习Git过程中想了解git reflog命令的高级用法与命令详解,于是找到了这几篇特别优秀的文章: [1]使用git reflog 命令来查看历史提交记录并使用提交记录恢复已经被 ...
- python之syslog学习 - 坏男孩 - 51CTO技术博客
python之syslog学习 - 坏男孩 - 51CTO技术博客 python之syslog学习 - 坏男孩 - 51CTO技术博客 python之syslog学习 2010-04-22 17:47 ...
- python 等高线地图图片转 tin_由等高线生成TIN并由TIN生成坡度图【解决中文环境翻译差别的问题】(转载请注明出自博客园)...
由等高线等生成TIN并生成坡度图的代码.在softline代码段对错误信息作了处理,不再使用"软线","软性线","柔性线","软 ...
- MD5算法在PB中的实现(转载自 - 阿多米 - 博客园)
MD5算法在PB中的实现(转载自 - 阿多米 - 博客园) 注:转载请写明出处.本文转载自--阿多米,原链接:http://www.cnblogs.com/zzjder/archive/2008/10 ...
- 关于 JavaScript 学习,一些好的博客或者网站
关于 JavaScript 学习,一些好的博客或者网站 我JavaScript学习过程中常去的一些网站与在知乎上看到的一些好的网站分享给大家: 1.首先增加一个重要的内容:JavaScript | M ...
- 关于iOS学习进阶的必读一些博客总结
关于iOS学习进阶的必读一些博客总结 作者 Raybon_lee 2016.01.16 22:28* 字数 3110 经过一周的思考还是决定重组一下优秀的博客,首次整理这些博客比较乱,但是后期会慢慢增 ...
- 如何转载别人优秀的博客----一定要标注原创出处
如何转载别人的博客 概述 我们有时候没有时间去写原创博客,但是又看到了一篇很不错的文章想收纳到自己的博客中怎么办呢?我们可以将别人的博客转载到自己的博客中. 注意事项 尊重原创的劳动成果,转载之前注意 ...
- 【转载】大叔推荐博客索引
原文地址:https://www.cnblogs.com/lori/archive/2013/01/22/2871029.html 大叔推荐文章系列 DotNetCore跨平台~文章索引-永久更新(N ...
最新文章
- linux脚本退出状态,Shell退出状态的使用
- html怎么让方块自动旋转,纯CSS3做的的3D旋转方块
- Dockerizing a Node.js web app
- 话说:学好C语言,走遍天下都不怕
- Leetcode 103. 二叉树的锯齿形层次遍历 解题思路及C++实现
- string替换_GEE数据类型—String,Number
- android activity dialog 高度,将Activity以Dialog形式显示,并设置宽高度
- 【项目】springboot中使用kaptcha生成验证码,登录时密码加盐处理
- 使用webpack配置react并添加到flask应用
- java 绘制长方形_Java入门:绘制简单图形
- springboot整合activemq加入会签,自动重发机制,持久化
- Python装饰器之一
- 看看MySQL几种主流备份方案的优缺点
- Angular动态加载组件报错:No component factory found for XXXXComponent. Did you add it to
- 重复率30%可以通过论文查重吗?
- ABAP 金额内外部转换函数
- 想学3D建模,去哪儿学比较好
- 计算机与计算思维读后感论文,读书笔记——计算思维培养的一点领悟与构想
- UI自动化偷懒必备:AirTest封装好ADB命令
- 不管你怎么赶,人生中总有抓不住的,享受当下吧
热门文章
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例(转)...
- java中jar打包的方法
- QTP11补丁下载 – 完美支持FIREFOX 9~10
- HTTP Server开发相关学习资料整理推介
- RAC环境下的备份与恢复(一)
- Windows xp/2003 中安装虚拟网卡 Microsoft Loopback Adapter
- linux内存之buff/cache
- 使用Formik轻松开发更高质量的React表单(一)入门
- 五分钟看懂UML类图与类的关系详解
- jackson 实体转json 为NULL或者为空不参加序列化