Ford_Fulkerson算法

在算法导论中对求解最大流问题给出了一般性的解决方法,但并没有涉及到具体的实现。在这里我还是重新的对求解最大流的思想进行一般性的描述,然后再给出具体的实现。

      Ford-Fulkerson方法依赖于三种重要思想,这三个思想就是在上一篇网络流基础中提到的:残留网络,增广路径和割。Ford-Fulkerson方法是一种迭代的方法。开始时,对所有的u,v∈V有f(u,v)=0,即初始状态时流的值为0。在每次迭代中,可通过寻找一条“增广路径”来增加流值。增广路径可以看成是从源点s到汇点t之间的一条路径,沿该路径可以压入更多的流,从而增加流的值。反复进行这一过程,直至增广路径都被找出来,根据最大流最小割定理,当不包含增广路径时,f是G中的一个最大流。在算法导论中给出的Ford-Fulkerson实现代码如下:

     FORD_FULKERSON(G,s,t)
     1   for each edge(u,v)∈E[G]
     2        do f[u,v] <— 0
     3            f[v,u] <— 0
     4   while there exists a path p from s to t in the residual network Gf
     5        do cf(p) <— min{ cf(u,v) : (u,v) is in p }
     6        for each edge(u,v) in p
     7             do f[u,v] <— f[u,v]+cf(p)         //对于在增广路径上的正向的边,加上增加的流
     8                  f[v,u] <— -f[u,v]                //对于反向的边,根据反对称性求

     第1~3行初始化各条边的流为0,第4~8就是不断在残留网络Gf中寻找增广路径,并沿着增广路径的方向更新流的值,直到找不到增广路径为止。而最后的最大流也就是每次增加的流值cf(p)之和。在实际的实现过程中,我们可以对上述代码做些调整来达到更好的效果。如果我们采用上面的方法,我们就要保存两个数组,一个是每条边的容量数组c,一个就是上面的每条边的流值数组f,在增广路径中判断顶点u到v是否相同时我们必须判断c[u][v]-f[u][v]是否大于0,但是因为在寻找增广路径时是对残留网络进行查找,所以我们可以只保存一个数组c来表示残留网络的每条边的容量就可以了,这样我们在2~3行的初始化时,初始化每条边的残留网络的容量为G的每条边的容量(因为每条边的初始流值为0)。而更新时,改变7~8行的操作,对于在残留网络上的边(u,v)执行c[u][v]-=cf(p),而对其反向的边(v,u)执行c[v][u]+=cf(p)即可。

      现在剩下的最关键问题就是如何寻找增广路径。而Ford-Fulkerson方法的运行时间也取决于如何确定第4行中的增广路径。如果选择的方法不好,就有可能每次增加的流非常少,而算法运行时间非常长,甚至无法终止。对增广路径的寻找方法的不同形成了求最大流的不同算法,这也是Ford-Fulkerson被称之为“方法”而不是“算法”的原因。下面将给出Ford-Fulkerson方法的具体实现细节:

int c[MAX][MAX];  //残留网络容量
int pre[MAX];  //保存增广路径上的点的前驱顶点
bool visit[MAX];

int Ford_Fulkerson(int src,int des,int n){  //src:源点 des:汇点 n:顶点个数
     int i,_min,total=0;
     while(true){
         if(!Augmenting_Path(src,des,n))return total; //如果找不到增广路就返回,在具体实现时替换函数名
         _min=(1<<30);
         i=des;
         while(i!=src){   //通过pre数组查找增广路径上的边,求出残留容量的最小值
             if(_min>c[pre[i]][i])_min=c[pre[i]][i];
             i=pre[i];
         }
         i=des;
         while(i!=src){    //再次遍历,更新增广路径上边的流值
             c[pre[i]][i]-=_min;
             c[i][pre[i]]+=_min;
             i=pre[i];
         }
         total+=_min;     //每次加上更新的值
     }
}


Edmonds-Karp算法实际上就是采用广度优先搜索来实现对增广路径的p的计算,代码如下:

bool Edmonds_Karp(int src,int des,int n){
     int v,i;
     for(i=0;i<n;i++)visit[i]=false;
     front=rear=0;     //初始化
     que[rear++]=src;
     visit[src]=true;
     while(front!=rear){     //将源点进队后开始广搜的操作
         v=que[front++];
        
//这里如果采用邻接表的链表实现会有更好的效率,但是要注意(u,v)或(v,u)有任何一条
         //边存在于原网络流中,那么邻接表中既要包含(u,v)也要包含(v,u)

         for(i=0;i<n;i++){ 
             if(!visit[i]&&c[v][i]){ 
//只有残留容量大于0时才存在边
                 que[rear++]=i;
                 visit[i]=true;
                 pre[i]=v;
                 if(i==des)return true;   //如果已经到达汇点,说明存在增广路径返回true
             }
         }
     }
     return false;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Ford-Fulkerson算法是一种解决最大流问题的算法,它通过不断寻找增广路径来增加流量,直到无法找到增广路径为止。在Matlab中,可以使用图论工具箱中的函数来实现Ford-Fulkerson算法,例如使用graph和maxflow函数。具体实现方法可以参考Matlab官方文档或相关教程。 ### 回答2: Ford-Fulkerson算法是求解最大流问题的一种经典算法,用于确定一个网络中从源节点到汇节点的最大可行流量。下面我将简要介绍如何使用Matlab实现Ford-Fulkerson算法。 首先,我们需要定义一个图结构来表示网络。可以使用邻接矩阵来表示有向图,其中矩阵元素表示边的容量。源节点可以用一个预先定义的节点索引表示,汇节点也可以用另一个预先定义的节点索引表示。 接下来,我们可以实现Ford-Fulkerson算法的关键步骤。算法的主要思想是在剩余网络上找到增广路径,并在这条路径上增加流量,直到不能找到增广路径为止。 具体实现中可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来找到增广路径。在每一次搜索过程中,我们需要判断当前节点是否已经被访问过,并且是否还可以通过当前边增加流量。 在找到增广路径后,我们可以计算出该路径上的最小容量(也称作瓶颈容量),并将该容量从剩余网络中减去。随后,我们将该容量添加到流网络中,并继续寻找新的增广路径。 当无法找到增广路径时,算法结束并返回最大流量值。最大流量值等于从源节点发出的所有流量之和。 综上所述,以上是在Matlab中实现Ford-Fulkerson算法的基本步骤。当然,具体实现中还需要考虑一些细节问题,并且可能需要调用一些Matlab内置的图算法函数来辅助实现。 ### 回答3: Ford-Fulkerson算法是用于求解最大流问题的一种常见算法,适用于有向图。算法的基本思想是不断在剩余网络中寻找一条增广路径,然后更新流量分布,直到无法找到增广路径为止。 在MATLAB中,可以使用图算法工具箱中的函数来实现Ford-Fulkerson算法。具体步骤如下: 1. 首先,需要创建一个有向图对象,并定义图中的节点和边。可以使用Graph对象来进行操作。 2. 然后,设置源节点和汇节点,即确定最大流的起点和终点。 3. 接下来,需要定义图中各个边的初始容量。可以使用addedge函数来添加边,并设置其容量。 4. 之后,可以使用fordfulkerson函数来求解最大流。该函数会返回一个最大流值,同时也会更新图中各个边的流量。 5. 最后,可以使用findedge函数来查找某条边的流量。该函数需要指定边的起点和终点节点,返回对应边的流量值。 需要注意的是,Ford-Fulkerson算法的复杂度较高,最坏情况下为O(f * m),其中f为最大流值,m为边的数量。因此,在处理大规模图的情况下可能会面临一定的挑战。 以上是用MATLAB实现Ford-Fulkerson算法的简要过程。通过使用MATLAB的图算法工具箱,可以方便地对最大流问题进行求解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值