算法实现(1):Ford-Fulkerson Algorithm

一、算法介绍

Ford-Fulkerson算法是一种最大流算法,其核心是通过引入“反向边”及“剩余图”的概念对原先的运输方案进行纠错、改进。引用卜东波老师“计算机算法设计与分析”讲义的描述如下:Ford-Fulkerson 算法引入反向边,让运出去的货物还可以有机会退回。将加入了退货边的图称为剩余图,构造剩余图的大致思路为,若 u → v 运了 f 吨货物,且容量限制为 C(u, v),则剩余图中 u 到 v 的正向弧 u → v 权值为 C(u, v) − f,表示最多还可再运 C(u, v) − f 吨货,并构造权值为 f 的反向弧,表示最多可退大小为f 的货物。

例如,下面两个图分别代表网络的流图及剩余图(剩余图中红色的边为“反向边”,即退货边)

流图及剩余图

Ford-Fulkerson算法过程的示意图如下:

Ford-Fulkerson算法过程

简单来说,就是原始流 + 剩余图中的可行路 = 原始流的一个改进。

二、Pseudo Code

令 p 表示剩余图 Gf 中的一条简单路径,称为增广路径。并定义 bottleneck(p, f) 为路径 p 上的最小容量边。则 Ford-Fulkerson 算法可以描述为:

这里写图片描述

算法开始,首先将所有边上的流量初始化为零,此时剩余图与原流图相同,然后进入循环,只要在剩余图中存在一条从s(源点)到t(终点)的路径,算法就执行以下步骤:任选一条s-t的路径,确定选择的s-t路径上的bottleneck(即该路径所包含的边的剩余流量的最小值),在该条路径上再流最小的剩余流量(即bottleneck值),最后更新流图及剩余图。直至在剩余图中不存在任何的s到t的路径,终止循环。

三、算法实现

1.实现环境:Windows 8, VS 2010;

2.图的数据结构——邻接矩阵:

本博文对算法的实现过程,采用邻接矩阵存储图信息,邻接矩阵存储图信息的详细过程参阅“图的存储表示——邻接矩阵”

3.完整程序详见Github,以下记录实现过程的难点:

(1) s-t路径搜索

程序中采用DFS(深度优先)算法搜索剩余图中的s-t路径,实际上是一种递归的思路,不断考察当前节点的邻居节点,看是否能到达终点t,若可以返回true,若不行则返回前一节点并考察前一节点的其他邻居节点。

/************************************************************************/  
/* 深度优先遍历(深度优先搜索)                                         */  
/************************************************************************/  
bool Graph::dfs(int source, bool* visited)  
{  
    // if current node is the destination node (t), then s-t path is found
    if(source == nodeNum - 1)
        return true;

    int destination;  
    visited[source] = true;          
    for(destination = 0; destination < nodeNum; destination++)  // search node adjacent to source  
    {
        // find adjacent node which has not been visited
        if(edge[source][destination]>0  && !visited[destination])  
        {
            // length of current path increase
            pathLength += 1;
            // add adjacent node to s-t path
            path[pathLength-1] = destination; 
            // go on searching adjacent node
            if( !(this -> dfs(destination, visited)) )
            {
                // if current adjacent node could not reach the final destinated node
                // pathLength decrease since it was increased presiously
                // continue to investigate the next adjacent node
                pathLength -= 1;
                continue;
            }
            else
            {
                // if current adjacent node could reach the final destinated node
                return true;
            }
        }
        else if(destination == nodeNum - 1)
            // no adjacent node, means no s-t path
            return false;
    }//end for
} 

(2) 主函数

以前文图示例子作测试,while循环中不断搜索s-t路径,直到剩余图中找不到s-t路径。当存在s-t路径时,如算法所述,取一s-t路径,找bottleneck,更新流与剩余图。

int main()
{
    // graph wiht node s, u, v, t
    char nodeName[nodeNum] = {'s', 'u', 'v', 't'};
    Graph graph = Graph(nodeNum);
    graph.setNode(nodeName);
    graph.setEdge('s', 'u', 1);
    graph.setEdge('s', 'v', 1);
    graph.setEdge('u', 'v', 1);
    graph.setEdge('u', 't', 1);
    graph.setEdge('v', 't', 1);

    // Ford-Fulkerson algorithm find maximum flow
    while(graph.findPath())
    {
        graph.printPath();
        graph.findBottleneck();
        graph.update();
    }

    // print maximum flow
    cout << "max flow: " << graph.getFlow() << endl;


    system("pause");
    return 0;
}

四、实现结果

打印算法实现的中间结果如下:
算法实现结果

  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值