最大流算法及其应用

合集下载

最大流问题的求解方法及应用

最大流问题的求解方法及应用

最大流问题的求解方法及应用
最大流问题,是指在一个有向图中,从源点 s 到汇点 t 的最大
流量。

在实际应用中,最大流问题往往用于描述网络传输、油管输送等流量分配问题。

求解最大流问题的方法包括以下几种:
1. 网络流算法:这是一种基于图论和线性规划的算法。

通过构建网络流图,将最大流问题转化为最小割问题,再利用线性规划求解最小割问题的对偶问题来求解最大流问题。

2. 增广路算法:这是一种经典的最大流算法,其基本思想是不断找到增广路径,即从源点 s 到汇点 t 的一条路径,沿途边权
均有剩余容量,使得该路径上的边的剩余容量中的最小值最大化,最终得到最大流。

3. 矩阵树定理:这是一种基于图论和矩阵运算的算法,适用于有向图和无向图。

通过计算图的拉普拉斯矩阵的行列式等方法,求得图的生成树个数,从而计算最大流。

4. Dinic算法:是对增广路算法的改进。

在增广路算法中,每
次查找增广路径的过程需要遍历整个图,为了提高效率,
Dinic算法引入了分层图的概念,将图分层之后只在图的一层
中查找增广路径,最终求得最大流。

这些方法在实际应用中常常被用来解决路由选择、网络流量优化、模拟电路分析等问题。

例如,最大流可以被用来优化数据传输、流水线设计、流量管道的运营和管理,提高资源利用率和数据传输速度。

最大流问题解题步骤

最大流问题解题步骤

最大流问题解题步骤一、什么是最大流问题?最大流问题是指在一个有向图中,给定源点和汇点,每条边都有一个容量限制,求从源点到汇点的最大流量。

该问题可以用于网络传输、电力调度等实际应用中。

二、最大流问题的解法1. 增广路算法增广路算法是最基本的解决最大流问题的方法。

其基本思想是不断地寻找增广路,并将其上的流量加入到原来的流中,直到不存在增广路为止。

具体步骤如下:(1)初始化网络中各边上的流量均为0;(2)在残留网络中寻找增广路;(3)如果存在增广路,则将其上的最小剩余容量作为增量加入到原来的流中;(4)重复步骤2和步骤3,直到不存在增广路。

2. Dinic算法Dinic算法是一种改进型的增广路算法,其核心思想是通过层次分析和分层图来减少搜索次数,进而提高效率。

具体步骤如下:(1)构建分层图;(2)在分层图上进行BFS搜索寻找增广路径;(3)计算路径上可行流量并更新残留网络;(4)重复步骤2和步骤3,直到不存在增广路。

3. Ford-Fulkerson算法Ford-Fulkerson算法是一种基于增广路的算法,其核心思想是不断地寻找增广路,并将其上的流量加入到原来的流中,直到不存在增广路为止。

具体步骤如下:(1)初始化网络中各边上的流量均为0;(2)在残留网络中寻找增广路;(3)如果存在增广路,则将其上的最小剩余容量作为增量加入到原来的流中;(4)重复步骤2和步骤3,直到不存在增广路。

三、最大流问题解题步骤1. 确定源点和汇点首先需要确定问题中的源点和汇点,这是解决最大流问题的前提条件。

2. 构建残留网络在有向图中,每条边都有一个容量限制。

我们可以将这些边看作管道,容量看作管道的宽度。

在实际传输过程中,某些管道可能已经被占用了一部分宽度。

因此,在求解最大流问题时,需要构建一个残留网络来表示哪些管道还能够继续传输数据。

具体方法是:对于每条边(u,v),分别构造两条边(u,v)和(v,u),容量分别为c(u,v)-f(u,v)和f(u,v),其中c(u,v)表示边的容量,f(u,v)表示当前流量。

最大流常见算法

最大流常见算法

最大流常见算法最大流问题是图论中的一个重要问题,其求解方法有多种,本文将介绍最常见的几种算法。

一、最大流问题简介最大流问题是在一个网络中寻找从源点到汇点的最大流量的问题。

网络是由一些节点和连接这些节点的边构成的,每条边都有一个容量,表示该边所能承载的最大流量。

源点是流量的起点,汇点是流量的终点。

在网络中,还可能存在其他节点和边。

二、Ford-Fulkerson算法Ford-Fulkerson算法是最早用于解决最大流问题的算法之一。

该算法基于增广路径来不断增加流量,直到无法再找到增广路径为止。

1. 算法步骤(1)初始化:将所有边上的流量设为0。

(2)寻找增广路径:从源点开始进行深度优先或广度优先搜索,在搜索过程中只选择剩余容量不为0且没有被标记过的边,并记录路径上容量最小值min。

(3)更新路径上各个边上的流量:将路径上各个边上的流量加上min。

(4)返回第二步,直到无法找到增广路径为止。

2. 算法分析Ford-Fulkerson算法可以保证在有限步内求解出最大流,但是其时间复杂度与增广路径的选择有关,最坏情况下可能需要指数级的时间复杂度。

三、Edmonds-Karp算法Edmonds-Karp算法是基于Ford-Fulkerson算法的一种改进算法。

该算法使用BFS来寻找增广路径,可以保证在多项式时间内求解出最大流。

1. 算法步骤(1)初始化:将所有边上的流量设为0。

(2)寻找增广路径:从源点开始进行BFS,在搜索过程中只选择剩余容量不为0且没有被标记过的边,并记录路径上容量最小值min。

(3)更新路径上各个边上的流量:将路径上各个边上的流量加上min。

(4)返回第二步,直到无法找到增广路径为止。

2. 算法分析Edmonds-Karp算法相对于Ford-Fulkerson算法来说,在同样的网络中,其时间复杂度更低,可以保证在O(VE^2)的时间内求解出最大流。

但是在某些特殊情况下仍然可能需要指数级时间复杂度。

最大流的概念

最大流的概念

最大流的概念最大流(Maximum Flow)是指在一个有向图中,给每条边一个容量限制,然后寻找一条从源点到汇点的路径,使得路径上的每条边的流量都不超过其容量限制的最大值。

最大流问题是网络流理论中的一种经典问题,具有广泛的应用领域,如网络优化、流量分配、资源调度等。

最大流问题可以用图论中的图来进行模型表示,其中图中的节点表示流经的位置,边表示流量通路,每条边还有一个容量值,表示该边所能承载的最大流量。

图中通常包括一个源点(Source)和一个汇点(Sink),各个节点与源点和汇点之间的连接关系构成了一个流量网络。

每个节点上的流量是指通过该节点的流量总和,而边上的流量是指该边上的实际流量。

最大流问题的求解可以采用不同的算法,其中最常见的是Ford-Fulkerson算法和Edmonds-Karp算法。

下面将对这两种算法进行详细介绍。

1. Ford-Fulkerson算法Ford-Fulkerson算法是最大流问题的经典算法,它的思想是不断寻找增广路径,并通过增加该路径上各边的流量来增加整个流量网络的流量。

算法的基本步骤如下:(1) 初始化流量网络的流量为0。

(2) 通过任意的路径查找算法(如深度优先搜索)找到一条从源点到汇点的增广路径。

(3) 在该增广路径上增加流量的值为该路径上残余容量的最小值。

(4) 更新整个流量网络中各边的残余容量和反向边的流量。

(5) 重复步骤2至4,直到无法找到增广路径为止。

2. Edmonds-Karp算法Edmonds-Karp算法是Ford-Fulkerson算法的一种改进,它通过使用广度优先搜索来寻找增广路径,使得算法的时间复杂度优于Ford-Fulkerson算法。

算法的具体步骤如下:(1) 初始化流量网络的流量为0。

(2) 通过广度优先搜索查找一条从源点到汇点的最短增广路径。

(3) 在该增广路径上增加流量的值为该路径上残余容量的最小值。

(4) 更新整个流量网络中各边的残余容量和反向边的流量。

最大流算法及其应用

最大流算法及其应用

最大流算法及其应用随着社会经济的发展和科技的进步,许多问题需要通过优化算法来解决,最大流算法就是其中之一。

最大流算法是在一个有向图中找到从源点到汇点的最大可能流的算法。

该算法在网络设计,交通流量控制,通信网络等领域有着广泛的应用。

1. 最大流问题在一个有向图G=(V,E)中,包含源点s和汇点t,每条边(u,v)上有一个容量c,表示该边的最大流量。

现要从源点到汇点流过尽可能多的流量,问最大可能的流量是多少?这就是最大流问题,寻找的答案是最大流量F。

2. 最大流算法最大流算法有多种实现方法,其中最著名的是 Ford-Fulkerson算法。

该算法的核心是寻找增广路径。

增广路径是一条从源点到汇点的路径,并且在该路径上所有边的容量都大于0。

通过将增广路径上的每一条边的流量都增加相同的值,就可以增加当前的流量。

重复这个过程直到不能再找到增广路径为止。

算法的详细步骤如下:1. 初始化所有边流量为0。

2. 查找增广路径。

可以使用深度优先搜索或广度优先搜索实现。

每找到一条增广路径就更新整个图的流量。

3. 重复步骤 2 直到无法再找到增广路径。

4. 输出最大流F。

该算法的时间复杂度不稳定,最差情况下是指数级的,但是由于增广路径的挖掘和流量的增加都是“往前走一步”,因此这种最长路径的情况是非常少见的。

在实际应用中,最大流算法基本上可以忽略这种情况。

3. 最大流算法应用(1) 网络设计在网络设计中,如果可以量化每个设备之间的容量,比如光缆的传输带宽,那么就可以使用最大流算法确定网络的最大传输能力。

如果网络的总传输能力超过了最大数据需求,那么可以减少设备之间的传输带宽,从而节省成本。

(2) 交通流量控制在城市交通中,最大流算法可以用来确定道路的拥堵情况,以及交叉路口的物流控制。

在公路建设中,如果能够准确地预测车辆数量和流量,就可以使用最大流算法确定道路的最大承载能力,从而保证交通的顺畅。

(3) 通信网络最大流算法也可以用于网络协议的设计。

dinic(最大流)算法讲解

dinic(最大流)算法讲解

dinic(最⼤流)算法讲解“⽹络流博⼤精深”—sideman语⼀个基本的⽹络流问题感谢WHD的⼤⼒⽀持最早知道⽹络流的内容便是最⼤流问题,最⼤流问题很好理解:解释⼀定要通俗!如右图所⽰,有⼀个管道系统,节点{1,2,3,4},有向管道{A,B,C,D,E},即有向图⼀张. [1]是源点,有⽆限的⽔量,[4]是汇点,管道容量如图所⽰.试问[4]点最⼤可接收的⽔的流量?这便是简单的最⼤流问题,显然[4]点的最⼤流量为50死理性派请注意:流量是单位时间内的,总可以了吧!然⽽对于复杂图的最⼤流⽅法是什么呢,有EK,Dinic,SAP,etc.下⾯介绍Dinic算法()Dinic 算法Dinic算法的基本思路:1. 根据残量⽹络计算层次图。

2. 在层次图中使⽤DFS进⾏增⼴直到不存在增⼴路3. 重复以上步骤直到⽆法增⼴引⾃,相当简单是吧...⼩贴⼠:⼀般情况下在Dinic算法中,我们只记录某⼀边的剩余流量.残量⽹络:包含反向弧的有向图,Dinic要循环的,每次修改过的图都是残量⽹络,层次图:分层图,以[从原点到某点的最短距离]分层的图,距离相等的为⼀层,(⽐如上图的分层为{1},{2,4},{3})DFS:这个就不⽤说了吧...增⼴ :在现有流量基础上发现新的路径,扩⼤发现的最⼤流量(注意:增加量不⼀定是这条路径的流量,⽽是新的流量与上次流量之差)增⼴路:在现有流量基础上发现的新路径.(快来找茬,和上⼀条有何不同?)剩余流量:当⼀条边被增⼴之后(即它是增⼴路的⼀部分,或者说增⼴路通过这条边),这条边还能通过的流量.反向弧:我们在Dinic算法中,对于⼀条有向边,我们需要建⽴另⼀条反向边(弧),当正向(输⼊数据)边剩余流量减少I时,反向弧剩余流量增加I Comzyh的较详细解释(流程) :Dinic动画演⽰1. ⽤BFS建⽴分层图注意:分层图是以当前图为基础建⽴的,所以要重复建⽴分层图2. ⽤DFS的⽅法寻找⼀条由源点到汇点的路径,获得这条路径的流量I 根据这条路径修改整个图,将所经之处正向边流量减少I,反向边流量增加I,注意I是⾮负数3. 重复步骤2,直到DFS找不到新的路径时,重复步骤1注意(可以⽆视):Dinic(其实其他的好多)算法中寻找到增⼴路后要将反向边增加IDinic中DFS时只在分层图中DFS,意思是说DFS的下⼀个节点的Dis(距源点的距离)要⽐⾃⼰的Dis⼤1,例如在图1中第⼀个次DFS中,1->2->4 这条路径是不合法的,因为Dis[2]=1;Dis[4]=1;步骤2中"获得这条路径的流量I "实现:DFS函数有参量low,代表从源点到现在最窄的(剩余流量最⼩)的边的剩余流量,当DFS到汇点是,Low便是我们要的流量I对于反向弧(反向边)的理解:这⼀段不理解也不是不可以,对于会写算法没什么帮助,如果你着急,直接⽆视即可.先举⼀个例⼦(如右图):必须使⽤反向弧的流⽹络在这幅图中我们⾸先要增⼴1->2->4->6,这时可以获得⼀个容量为 2的流,但是如果不建⽴4->2反向弧的话,则⽆法进⼀步增⼴,最终答案为2,显然是不对的,然⽽如果建⽴了反向弧4->2,则第⼆次能进⾏ 1->3->4->2->5->6的增⼴,最⼤流为3.Comzyh对反向弧的理解可以说是"偷梁换柱",请仔细阅读: 在上⾯的例⼦中,我们可以看出,最终结果是1->2->5->6和1->2->4->6和 1->3->4->6.当增⼴完1->2->4->6(代号A)后,在增⼴ 1->3->4->2->5->6(代号B),相当于将经过节点2的A流从中截流1(总共是2)⾛2->5>6,⽽不⾛2->4>6了,同时B流也从节点4截流出1(总共是1)⾛4->6⽽不是4->2->5->6,相当于AB流做加法.简单的说反向弧为今后提供反悔的机会,让前⾯不⾛这条路⽽⾛别的路.Dinic算法的程序实现最⼤流算法⼀直有⼀个⼊门经典题: 或者是这两个是同⼀个题给出这道题的代码1 #include<cstdio>2 #include<cstring>3 #include<cmath>4 #include<iostream>5 #include<algorithm>6 #include<set>7 #include<map>8 #include<queue>9 #include<vector>10 #include<string>11#define Min(a,b) a<b?a:b12#define Max(a,b) a>b?a:b13#define CL(a,num) memset(a,num,sizeof(a));14#define eps 1e-1215#define inf 0x7fffffff1617//freopen("data.txt","r",stdin);18const double pi = acos(-1.0);19 typedef __int64 ll;20const int maxn = 300 ;21using namespace std;22int n , m;23int flow[maxn][maxn],dis[maxn] ;//dis[i],表⽰到原点 s 的层数2425int bfs()// 重新建图(按层数建图)26 {27 CL(dis,-1);28 dis[1] = 0 ;29 queue<int>que;30 que.push(1);31while(!que.empty())32 {33int k = que.front();que.pop() ;34for( int i = 1;i<= n;i++)35 {36if(flow[k][i] > 0 && dis[i] < 0 )// 如果可以可以到达但还没有访问37 {38 dis[i] = dis[k]+ 1 ;39 que.push(i) ;40 }41 }42 }4344if(dis[n] > 0) return1;45else return0 ;4647 }48int dfs(int x,int mx)// 查找路径上的最⼩的流量49 {5051int i , a ;52if(x == n) return mx ;5354for(i = 1;i<= n;i++)55 {56if(flow[x][i] > 0 && dis[i] == dis[x] + 1 && (a =dfs(i,min(mx,flow[x][i]))))57 {58 flow[x][i] -= a;59 flow[i][x] += a;60return a ;616263 }64 }65return0 ;66 }67int main()68 {69//freopen("data.txt","r",stdin);70int i ,s,e,c;71while(scanf("%d%d",&m,&n)!=EOF)72 {73 CL(flow,0);74for(i = 0 ; i < m;i++)75 {76 scanf("%d%d%d",&s,&e,&c);77 flow[s][e] += c;78 }79int ans = 0;80int res;8182while(bfs())83 {848586while(res = dfs(1,inf)) ans+= res ;8788 }89 printf("%d\n",ans);90 }9192 }更⾼效的 dinichdu 4292 Food#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>#include<map>#include<queue>#include<vector>#include<string>#define INF 0x3fffffff#define F(x) (x)#define N(x) (205+(x))#define CPN(x) (410+(x))#define D(x) (615+(x))#define maxn 250#define CL(a,b) memset(a,b,sizeof(a))#define Pnum 210using namespace std;int next[maxn*20],dis[maxn*10];int s,e;int n, fnum ,dnum ,f[maxn],d[maxn],cnt;struct node{int to;int cap ;int next ;}p[200000] ;int que[maxn*maxn] ,idx;void add(int x,int y,int cap)// 建边注意反向边的流量为 0{p[cnt].to = y;p[cnt].cap = cap ;p[cnt].next = next[x];next[x] = cnt++ ;p[cnt].to = x;p[cnt].cap = 0;p[cnt].next = next[y];next[y] = cnt++ ;}int bfs()// 重新建图(按层数建图){memset(dis,0xff,sizeof(dis)) ;dis[s] = 0 ;queue<int>que;que.push(s);while(!que.empty()){int k = que.front();que.pop() ;for( int i = next[k];i!=-1;i = p[i].next){int v = p[i].to;int cap = p[i].cap ;if(cap > 0 && dis[v] < 0 )// 如果可以可以到达但还没有访问 {dis[v] = dis[k]+ 1 ;que.push(v) ;}}}if(dis[e] > 0) return1;else return0 ;}int dfs(int x,int mx)// 查找路径上的最⼩的流量{int i , a ,tf = 0;if(x == e) return mx ;for(i = next[x];i!= - 1;i = p[i].next){int v = p[i].to ;int cap = p[i].cap ;if(cap > 0 && dis[v] == dis[x] + 1 && (a =dfs(v,min(cap,mx)))){p[i].cap -= a;p[i^1].cap += a;return a;}}if(!tf) dis[x] = -1;// 没有找到最⼩流量,说明从这个点到不了终点,所以标记⼀下return tf ;}int main(){int i , j ;char c[250] ;//freopen("data.txt","r",stdin) ;while(scanf("%d%d%d",&n,&fnum,&dnum)!=EOF){CL(next,-1) ;cnt = 0;s = 0;e = 2000;for(i = 1 ; i <= fnum;i++){scanf("%d",&f[i]);}for(i = 1 ; i<= dnum;i++){scanf("%d",&d[i]) ;}for(i = 1; i <= n;i++)// ⼈和吃的{scanf("%s",c);for(j = 0 ; j< fnum ;j++){if(c[j] == 'Y'){add(j + 1,i + Pnum,1) ;}}}for(i = 1; i<= n;i++)// ⼈和喝的{scanf("%s",c);for(j = 0 ; j< dnum ;j++){if(c[j] == 'Y'){add(i + Pnum*2,j + Pnum*3 + 1,1) ;}}}for(i = 1; i <= fnum;i++)//增加源点{add(0,i,f[i]) ;}for(i = Pnum*3 + 1,j = 1; j <= dnum;i++,j++)//增加汇点 {add(i,e,d[j]) ;}for(i = 1; i <= n;i++)// 将⼈拆分{add(i + Pnum,i +Pnum*2,1);}int ans = 0;int res;while(bfs()){while(res = dfs(s,INF)) ans+= res ;}printf("%d\n",ans);}}。

最大流算法在网络优化中的应用

最大流算法在网络优化中的应用

最大流算法在网络优化中的应用最大流算法是一种常用的图论算法,用于解决网络中流量分配的问题。

它在许多领域中都有广泛的应用,尤其在网络优化中发挥着重要的作用。

本文将介绍最大流算法的原理和几个具体应用案例。

一、最大流算法原理最大流算法的核心思想是通过构建一个有向图来描述网络流量的传递。

在图中,节点代表网络中的顶点或交叉点,边表示两个节点之间的连接。

每条边上都有一个容量,表示该边能够传递的最大流量。

最大流算法通过从源节点(Source)向汇节点(Sink)不断推送流量,并更新路径上的容量,直到不能再推送为止。

这样,最终的结果就是源节点向汇节点的最大流量。

二、最大流算法的应用1. 网络流量优化在计算机网络中,最大流算法被广泛应用于网络流量的优化问题。

通过最大流算法,可以确定从源节点到汇节点的最大可用带宽,从而实现网络资源的合理分配和利用。

在网络拓扑结构复杂的大型系统中,最大流算法能够帮助我们优化网络性能,提高数据传输效率。

2. 电力网络调度在电力系统中,最大流算法可以用来解决电力网络调度问题。

通过最大流算法,可以确定发电站到用户之间的最大功率传输,从而实现电力的高效分配。

在电力系统的规划和管理中,最大流算法能够帮助我们确保电力供需平衡,提高电网的可靠性和稳定性。

3. 交通网络优化最大流算法还可以用于交通网络的优化。

通过最大流算法,可以确定交通网络中各路段的最大通过能力,从而实现交通流量的合理调度。

在城市交通规划和管理中,最大流算法能够帮助我们减少交通拥堵,提高交通效率,优化交通资源的利用。

4. 供应链管理在供应链管理中,最大流算法可以用来优化物流路径和资源分配。

通过最大流算法,可以确定供应链中各个节点之间的最大货物流量,从而实现供应链的高效运作。

在供应链的规划和执行中,最大流算法能够帮助我们减少成本,提高服务水平,实现资源的最优配置。

三、总结最大流算法在网络优化中具有广泛的应用。

通过构建有向图模型,最大流算法能够帮助我们解决网络中的流量分配问题,实现资源的最优配置和利用。

最大流问题的几种经典解法综述

最大流问题的几种经典解法综述

最⼤流问题的⼏种经典解法综述⼀、什么是最⼤流问题假设现在有⼀个地下⽔管道⽹络,有m根管道,n个管道交叉点,现在⾃来⽔⼚位于其中⼀个点,向⽹络中输⽔,隔壁⽼王在另外⼀个点接⽔,已知由于管道修建的年代不同,有的管道能承受的⽔流量较⼤,有的较⼩,现在求在⾃来⽔⼚输⼊的⽔不限的情况下,隔壁⽼王能接到的⽔的最⼤值?为解决该问题,可以将输⽔⽹络抽象成⼀个联通的有向图,每根管道是⼀条边,交叉点为⼀个结点,从u流向v的管道能承受的最⼤流量称为容量,设为cap[u][v],⽽该管道实际流过的流量设为flow[u][v],⾃来⽔⼚称为源点s,隔壁⽼王家称为汇点t,则该问题求的是最终流⼊汇点的总流量flow的最⼤值。

⼆、思路分析关于最⼤流问题的解法⼤致分为两类:增⼴路算法和预流推进算法。

增⼴路算法的特点是代码量⼩,适⽤范围⼴,因此⼴受欢迎;⽽预流推进算法代码量⽐较⼤,经常达到200+⾏,但运⾏效率略⾼,如果腹⿊的出题⼈要卡掉⼤多数⼈的code,那么预流推进则成为唯⼀的选择。

( ⊙ o ⊙ )咳咳。

先来看下增⼴路算法:为了便于理解,先引⼊⼀个引理:最⼤流最⼩割定理。

在⼀个连通图中,如果删掉若⼲条边,使图不联通,则称这些边为此图的⼀个割集。

在这些割集中流量和最⼩的⼀个称为最⼩割。

最⼤流最⼩割定理:⼀个图的最⼤流等于最⼩割。

⼤开脑洞⼀下,发现此结论显⽽易见,故略去证明(其实严格的证明反⽽不太好写,但是很容易看出结论是对的,是吧)。

这便是增⼴路算法的理论基础。

在图上从s到t引⼀条路径,给路径输⼊流flow,如果此flow使得该路径上某条边容量饱和,则称此路径为⼀条增⼴路。

增⼴路算法的基本思路是在图中不断找增⼴路并累加在flow中,直到找不到增⼴路为⽌,此时的flow即是最⼤流。

可以看出,此算法其实就是在构造最⼩割。

增⼴路算法⽽预流推进算法的思路⽐较奇葩(没找到⽐较好的图,只能⾃⾏脑补⼀下了。

= =#):先将s相连的边流⾄饱和,这种边饱和的结点称为活动点,将这些活动点加⼊队列,每次从中取出⼀个点u,如果存在⼀个相邻点v是⾮活动点,则顺着边u->v 推流,直到u变为⾮活动点。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

条最短增广路。当找不到允许路的时候,我们需要修改某些点的 d (i) 。
算法伪代码如下:
SAP-ALGORITHM (G, s, t)
1 initialize flow f to 0
2 do BFS to calculate d of each vertex
// In fact, we can initialize d to 0. 3 i←s
第 5 页 共 15 页
最大流算法及其应用
修改前 d (i) < d ( j) +1,而修改后会存在 d (i) = d ( j) +1,因此 d (i) 变大了),所以 说 d (i) 是单调递增的,这就提示我们,如果 d 函数出现了“断层”,即没有 d (i) = k , 而有 d (i) = k ±1 ,这时候必定无法再找到增广路径。我们可以这么想,现在的 i 满足 d (i) = k +1 ,发现没有一个 d ( j) 为 k,因此就会尝试去调整 d (i) ,但是 d (i) 是 单调递增的,只会越来越大,所以 k 这个空缺便永远不会被补上,也就是说无法 再找到增广路径。
最小割是指流网络中容量最小的割。 Ford-Fulkerson 定理(最小割最大流定理):在流网络中,最小割的容量等 于最大流的流量。(证明也在此略去) 根据这个定理,我们就可以通过求流网络的最大流来得到最小割。
3. 最大流算法
前面所讲的只是求最大流的一种方法,但怎样高效地实现还是一个问题。 这个方法的最大问题就在于怎样快速地找到一条增广路径。当然我们可以用 最基本的搜索(DFS 或 BFS),但是这种方法肯定不够高效,这时我们就需要更 高效的算法。 本文将重点介绍一种高效且实用的最大流算法:SAP 算法(最短增广路算 法)。 最短增广路算法(Shortest Augmenting Path Algorithm),即每次寻找包
最大流算法及其应用
最大流算法及其应用
南京外国语学校 贾志鹏
【关键词】网络流、最大流问题、最小割问题 【摘要】本文介绍了一种特殊的图——流网络及其相关问题,主 要介绍的是最大流问题和最小割问题,并提出了解决方案。最后 介绍了一些网络流相关的建模问题。 【目录】
一、网络流相关的一些概念
(1)流网络 (2)流 (3)割 (4)残留网络 (5)增广路径 (6)增广
再来看一道例题:POJ 3281 Dining (USACO 2007 Open Gold) 题目意思比较简单,就是说现在有 N 只奶牛,F 种食物和 D 种饮料,每只奶 牛喜欢其中的一些食物和饮料。现在每种食物和饮料只能分给一只奶牛,每只奶
第 7 页 共 15 页
最大流算法及其应用
牛也只能吃一种食物和一种饮料,问最多能使多少奶牛既吃到食物又喝到饮料。 这个题和二分图匹配有相似之处,但又不完全相同,我们可以沿着二分图匹
第 3 页 共 15 页
最大流算法及其应用
减去 p 的残留容量,cf (v,u) 加上 p 的残留容量。(程序实现基本都是通过直接修 改残留网络来实现增广的)
二、最大流和最小割问题
1. 最大流问题
对于一个流网络 G = (V , E) ,其流量 f 的最大值称为最大流,最大流问题就 是求一个流网络的最大流。
反对称性:对所有 u, v ∈V ,要求 f (u, v) = − f (v,u) 。
流守恒性:对所有 u ∈V −{s,t} ,要求 ∑ f (u, v) = 0 。 v∈V
整个流网络 G 的流量 f = ∑ f (s, v) 或 f = ∑ f (u,t) 。
v∈V
u∈V
3. 割 (Cut)
流网络 G = (V , E) 的割 (S,T ) 将V 划分成 S 和 T = V − S 两部分,使得 s ∈ S ,
加了以上两个优化,SAP 的效率是十分高的(可以见后面的测试),并且需 要增加的代码量都很少,也没有增加什么额外的判断时间,因此是十分有用的。
三、最大流算法的应用
在现在的信息学竞赛中,一般不会考裸的最大流问题,而是把问题转化为最 大流或最小割模型,这使得题目有了难度。
1. 最大流模型
一个典型的最大流模型就是二分图的最大二分匹配。 二分图 G = (X ,Y, E) ,其中 X 和 Y 是两个不相交的点集,并且对于每对 (u, v) ∈ E , u ∈ X 且 v ∈Y 。二分图的最大二分匹配问题就是从 E 中选择一些边, 使得每个点最多在选择的边里出现一次,问最多能选多少条边。
15
i ← last vertex in p
16 return f 整个算法实际上就是一个 DFS 的过程,但是没有写成递归的形式,是为了
防止流网络的点数过多而栈溢出。
SAP 算法有两个重要的优化:Gap 优化和当前弧优化。
Gap 优化:我们可以注意到由于残留网络的修改只会使 d (i) 越来越大(因为
第 4 页 共 15 页
最大流算法及其应用
含弧的个数最少的增广路进行增广,可以证明,此算法最多只需要进行 V E 次 2
增广。并且引入距离标号的概念,可以在 O(V ) 的时间里找到一条最短增广路。
最终的时间复杂度为 O(V 2 E ) ,但在实践中,时间复杂度远远小于理论值(特 别是加了优化之后),因此还是很实用的。
增广路定理:当且仅当由当前的流 f 压得的残留网络 Gf 中不存在增广路径
时,流 f 的流量 f 达到最大。(证明在此略去,可以参见相关书籍) 根据增广路定理,我们可以设计出最基本的求最大流的方法,一开始将流网
络 G = (V , E) 的流 f 置为零流,即对于 (u, v) ∈ E 时, f (u, v) = 0 。然后构建残留网 络,寻找增广路径增广,再修改残留网络,重复此过程,直到无法找到增广路径。 此方法(之所以不是算法,是因为实现方法很多)称为 Ford-Fulkerson 方法。
s
t
图 4 新建的流网络(图中弧的容量均为 1)
对于每个左边的点,进去的流量最多只有 1;对于每个右边的点,出去的流 量最多只有 1,所以每个点最多在选中的边里最多出现一次(选中的边即为中间 流量为 1 的弧)。又因为流最大,所以结果就是原二分图的最大二分匹配。
关于二分图的最大二分匹配还有另外一种算法:匈牙利算法,由于其可以更 简单地实现,所以在竞赛中往往不使用最大流,但这种建模方式值得借鉴。
第 6 页 共 15 页
最大流算法及其应用
图 3 一个二分图 的例子及其最大匹 配(实线表示选中 的边,虚线表示未 选中的边)ห้องสมุดไป่ตู้
由于每个点只能在选择的边里出现一次,就此我们可以联想到了流的容量限 制 f (u, v) ≤ c(u, v) ,因此我们控制经过每个点的流量不超过 1 即可保证每个点只 被使用一次。这样我们就得到了一个思路:增加源点和汇点,从源点到左边的每 个点连边,从右边的每个点到汇点连边,容量都为 1。两边点中间的边保持不变, 只是改成有向边,从左边指向右边。
t ∈T 。定义割 (S,T ) 的容量为 c(S,T ) ,则:
第 2 页 共 15 页
c(S,T ) = ∑ c(u, v) u∈S ,v∈T
最大流算法及其应用
3 s
5
2 2
1
1 3
2
4 t
4
6
图 2 一个割的例子(边上的数字表示该弧的容量,割的 容量即为 2+2+1+6=11)
4. 残留网络 (Residual Network)
5. 增广路径 (Augmenting Path)
对于残留网络 Gf 中的一条 s-t 路径 p 称其为增广路径,定义增广路径 p 的残 留容量为 p 上弧容量的最小值。后面求最大流要用到增广路径这个概念。
6. 增广 (Augment)
对于残留网络 Gf 中的一条增广路径 p,增广的意思就是对于每一条属于 p 的弧 (u, v) ,将 f (u, v) 增加 p 的残留容量,将 f (v,u) 减少 p 的残留容量。这样的 话,新的流 f 仍然满足流的三条性质,并且原流网络的流量 f 增加了。一般来 说,增广过后就会修改残留网络,易得对于每一条属于 p 的弧 (u, v) ,要将 cf (u, v)
4 while d(s) < n // n is the amount of vertexes in G
5
if there exists j that (i,j)∈Ef and d(i)=d(j)+1
6 then do add vertex i into augmenting path p
7
i←j
8
距离标号:对于每个顶点 i 赋予一个非负整数值 d (i) 来描述 i 到 t 的“距离” 远近,称它为距离标号,并且满足以下两个条件:
(1) d (t) = 0 。
(2)对于残留网络 Gf 中的一条弧 (i, j) , d (i) ≤ d ( j) +1。 如果残留网络 Gf 中的一条弧 (i, j) 满足 d (i) = d ( j) +1 ,我们称 (i, j) 是允许 弧,由允许弧组成的一条 s-t 路径是允许路。显然,允许路是残留网络 Gf 中的一
if i=t
9
then do augment flow f along p
10
i←s
11 else if there exists j that (i,j)∈Ef
12
then d(i) ← min{ d(j)+1 | (i,j)∈Ef }
13
else d(i) ← n
14
if i≠s then do delete i in augmenting path p
3 s
5
2 2
1
1 3
2
4 t
相关文档
最新文档