Ford-Fulkerson & EK - 学习笔记

之前网络流什么的快忘完了

老师讲课的时候一脸懵逼……开始系统复习,从最大流开始

标签:网络流-最大流


『预备』

首先复习了网络流的概念——

网络流是一个有向图,每一条边有一个流量限制(也可以叫做边权),图上有且仅有两个特殊点:源点-入度为0、汇点-出度为0。除此之外的所有点都有出度和入度。

网络流类似于“水流”,源点就相当于“无穷的水源”,从源点出发向其相邻边“流水”,边上“水”的流量不能超过其流量限制(容量限制),且对于每个点(除源点、汇点),流入该点的“水量”等于该点流出的“水量”(流守恒性)。

其次网络流具有斜对称性,即对于一条边,若它的流量为f,则它的反向边流量为 -f。

(下面简写源点为Begin,汇点为End,网络的边集为 E、点集为 V)

用式子的方法总结一下网络流所具有的性质:

定义\(f(u,v)\)表示u到v的边的流量,\(c(u,v)\)表示u到v的边的流量限制(容量);只对相邻的 u,v 有此定义。

\[\begin{cases}
f(u,v)<c(u,v)\\
f(u,v)=-f(v,u)\\
\sum_v f(u,v)=\sum_w f(w,u)
\end{cases}
\]

定义网络流的 流f 为:\(f=\sum_v f(Begin,v)=\sum_w f(w,End)\)

定义u到v的边的残留容量r(u,v)为:\(r(u,v)=c(u,v)-f(u,v)\)

最大流即流网络中的最大流值。

EK算法是对Ford-Fulkerson方法的实现。


『Ford-Fulkerson方法』

「残留网络&增广路」

如果 \(r(u,v)>0\),则边 (u,v) 在残留网络中。

增广路是残留网络中从 Begin 到 End 的一条路径 P,\(\delta(P)=\min\{r(u,v)\},(u,v)\in P\) 表示增广路P的残留容量。

「方法」

Ford-Fulkerson方法的主要思想是先构造残余, DFS 找到一条增广路,然后找到增广路上的流量 \(\delta\),将增广路上的每一条边的流量限制都减去 \(\delta\)、每一条边都反向边都流量限制都加上 \(\delta\) 。

为什么要把反向边的流量限制加上 \(\delta\) 呢?我们来看一个简单的例子:



如果我们一开始选择流“1-2-3-4”,那么我们得到流的大小为1,但是显然我们可以选择流“1-2-4 , 1-3-4”,流的大小为2。

如果先流“1-2-3-4”,那么我们就相当于确定了边 (2,3) 必须流,但是这是不一定的。我们给它的反向边 (3,2) 加上 \(\delta\)(最初所有边的反向边的流量限制都为0),那么下一次我们流过它的反向边 (3,2) 时,就相当于“撤销”了流过 (2,3)。然后两次的流量之和就是最大流。

为什么这样是正确的?

让我们手推一下这张图的最大流过程:先找到了“1-2-3-4”,然后 (1,2)(2,3)(3,4) 的流量限制减去10,(2,1)(3,2)(4,3) 加上10;再流过 “1-3-2-4”。就相当于把原来“1-2-3-4”的(2,3)断开,接上(2,4)形成“1-2-4”;而断开过后的“2-3-4”中,流过反向边(3,2)使得(2,3)的流被撤销,再接上(1,3)就形成“1-3-4”。


『EK算法』

一种比较基础的对Ford-Fulkerson方法的实现,基于BFS。

首先定义一些数组,方便后面阐述:

(1) vis[u] 表示点 u 在该次BFS中是否被访问过

(2) flw[u] 表示该次BFS中从源点开始流到点 u 的流最大的值(也就是源点BFS到u的路径上的边的最小的流量限制)

(3) preedg[u] 表示该次BFS中是从哪一条边流到u的

「BFS部分」

从源点开始,BFS遍历整个流网络,要求经过的有向边的流量限制严格大于0,并且不重复经过同一个点。当遍历到汇点时,返回当前流值。

假设现在要从u流到v,先要保证 vis[v] == 0 并且 (u,v) 的流量限制大于0。然后标记 vis[v] ,再记录 preedg[v] 为当前边的编号;flw[v] 的计算类似于 dp,因为流值最大不超过 (u,v) 的限制,那么递推式也非常显然 \(flw[v]=\min\{flw[u],c(u,v)\}\)。

如果v就是汇点,则返回 flw[v],否则将v压入队列。

如果最后无法到达汇点,则返回0,表示无增广路。

「EK算法主部分」

先BFS判断当前是否有增广路,如果有,则BFS返回值则为增广路的流量 \(\delta\),则从v沿着增广路倒过来回到源点,并将增广路上的边的流量限制减去 \(\delta\),增广路上的边的反向边的流量限制加上 \(\delta\) 。直到没有增广路(BFS返回值为0),退出循环。

其实就是把 Ford-Fulkerson 方法模拟了一遍。

因此EK算法的时间复杂度并不理想,但毕竟它是(似乎是)最大流算法中最为稳定的算法,有其存在的价值。

「模板代码」

〔洛谷 P2740〕为原题的代码~

/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=200;
struct FLOWGRAPH{
struct NODE{
int to,nxt,lim,rev;
NODE(){}
NODE(int _to,int _nxt,int _lim,int _rev):
to(_to),nxt(_nxt),lim(_lim),rev(_rev){}
}nod[N*2+7];
int cnt,adj[N+7];
void Rebuild(){
memset(adj,-1,sizeof adj);
cnt=0;
}
void AddEdge(int u,int v,int lim){
int A=++cnt,B=++cnt;
nod[A]=NODE(v,adj[u],lim,B),adj[u]=A;
nod[B]=NODE(u,adj[v],0,A),adj[v]=B;
}
}grp;
int m,n;
int preedg[N+7],flw[N+7],vis[N+7];
int BFS(int cas){
queue<int> que;
que.push(1);
flw[1]=(1<<30);
while(!que.empty()){
int u=que.front();que.pop();
for(int i=grp.adj[u];i!=-1;i=grp.nod[i].nxt){
int v=grp.nod[i].to;
if(!grp.nod[i].lim || vis[v]==cas) continue;
vis[v]=cas;
preedg[v]=i;flw[v]=min(grp.nod[i].lim,flw[u]);
if(v==n) return flw[v];
que.push(v);
}
}
return 0;
}
int EK(){
int del,res=0,cas=0;
while(del=BFS(++cas)){
int pnt=n;
while(pnt!=1){
grp.nod[preedg[pnt]].lim-=del;
grp.nod[grp.nod[preedg[pnt]].rev].lim+=del;
pnt=grp.nod[grp.nod[preedg[pnt]].rev].to;
}
res+=del;
}
return res;
}
int main(){
grp.Rebuild();
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
int u,v,lim;
scanf("%d%d%d",&u,&v,&lim);
grp.AddEdge(u,v,lim);
}
int res=EK();
printf("%d\n",res);
return 0;
}

\(\mathcal{The\ End}\)

\(\mathcal{Thanks\ For\ Reading!}\)

如果有没看懂或者有问题的,请咨询作者邮箱\(lucky\_glass@foxmail.com\)~

学习笔记 - Ford-Fulkerson & EK的更多相关文章

  1. [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. [原创]java WEB学习笔记98:Spring学习---Spring Bean配置及相关细节:如何在配置bean,Spring容器(BeanFactory,ApplicationContext),如何获取bean,属性赋值(属性注入,构造器注入),配置bean细节(字面值,包含特殊字符,引用bean,null值,集合属性list map propert),util 和p 命名空间

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. ADO.NET Entity Framework学习笔记(3)ObjectContext

    ADO.NET Entity Framework学习笔记(3)ObjectContext对象[转]   说明 ObjectContext提供了管理数据的功能 Context操作数据 AddObject ...

  4. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  5. 23 DesignPatterns学习笔记:C++语言实现 --- 2.2 Adapter

    23 DesignPatterns学习笔记:C++语言实现 --- 2.2 Adapter 2016-07-22 (www.cnblogs.com/icmzn) 模式理解

  6. JavaScript:学习笔记(4)——This关键字

    JavaScript:学习笔记(4)——This关键字 以前这篇帖子是关于闭包的,但是我想弄明白的其实是This关键字.JavaScript的this和Java等面向对象语言中的this大不一样,bi ...

  7. matlab学习笔记12_4rmfield,arrayfun,structfun,struct2cell,cell2struct

    一起来学matlab-matlab学习笔记12 12_4 结构体 rmfield,arrayfun,structfun,struct2cell,cell2struct 觉得有用的话,欢迎一起讨论相互学 ...

  8. Spring学习笔记(一)

    Spring学习笔记(一) 这是一个沉淀的过程,大概第一次接触Spring是在去年的这个时候,当初在实训,初次接触Java web,直接学习SSM框架(当是Servlet都没有学),于是,养成了一个很 ...

  9. day64—ajax技术学习笔记

    转行学开发,代码100天——2018-05-19 Ajax技术学习笔记 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).AJA ...

随机推荐

  1. vue中数组删除,页面没重新渲染

    创建一个组件时,数据类型是数组,在删除这个数组中的数据时,数组中的数据是对的,但页面渲染的数据却不对. 举例:(不一定复现) <ul> <li v-for="(item, ...

  2. Python基础-简介二

    一.变量类型 变量存储在内存中的值.这就意味着在创建变量时会在内存中开辟一个空间. 基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中. 因此,变量可以指定不同的数据类型,这些 ...

  3. iSCSI配置

    iSCSI介绍 几种存储的架构: 直接存取 (direct-attached storage):例如本机上面的磁盘,就是直接存取设备: 透过储存局域网络 (SAN):来自网络内的其他储存设备提供的磁盘 ...

  4. CentOS 7 下 安装Webmin 启动防火墙失败----Applying firewall rules:iptables-restore:line 2 failed

    最近学习CentOS 7 系统管理,使用的是<CentOS 6.X系统管理实战宝典>一书------因为网购的CentOS 7 的书还没有送到 O(‘  ’!!)O~ (1)先使用yum方 ...

  5. 浅谈回归(二)——Regression 之历史错误翻译

    我很好奇这个问题,于是搜了一下.我发现 Regression 这个词 本意里有"衰退"的意思. 词根词缀: re- 回 , 向后 + -gress- 步 , 级 + -ion 名词 ...

  6. 【Android】移动项目位置

    一.前言 有时候,我们新建一个项目后,因为一些原因想要重新移动项目到别的文件夹.然而,移动到新的文件夹后,却发现之前好好的项目运行不了.点击运行后,弹出如下对话框.  Installation fai ...

  7. 二、docker学习笔记——安装redis

    前提:打开powershell(管理员) 1.官网路径 按照官网的做了,但外网无法链接,只好换个做法. 2.docker pull redis 这下载的最新版redis 3.在docker上挂载文件夹 ...

  8. UNIX和linux系统性能监控工具oswatcher

    可以在一台机器上运行oswatcher.把运行的结果拷贝到有vnc的机器上进行分析.java -jar oswbba.jar -i /mnt/hgfs/database/oswbb/archive . ...

  9. Java日志系统

    前言 各组件之间的关系: slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实 ...

  10. C#中internal关键字

    对于一些大型的项目,通常由很多个DLL文件组成,引用了这些DLL,就能访问DLL里面的类和类里面的方法.比如,你写了一个记录日志的DLL,任何项目只要引用此DLL就能实现记录日志的功能,这个DLL文件 ...