算法思想:
解决最大流问题我们可以利用增广路径来增加流量,然后通过一次次的迭代将增光路径全部找出,此时从源点出发的流量和就是此网络的最大流量。而确定每一次增广路径的流量都需要用到残留流量等方法计算。以下就是将这个方法的具体实现算法展现出来:
1、将流网络用矩阵数组的方式存储。如共有n个点则创造一个n*n的数组a,每个数组的值都表示那条路径的权重,如a[1][3]的值若不为0则表示从点1到点3有路径。其中特别注意的是有以下几点:(1)、矩阵中无任何边指向源点,汇点也无任何边指其他点。即矩阵的第一列和最后一行均为0。(2)、矩阵中无两条平行反向边,如1指向3后3不能指向1。(3)、自己不能形成环,即自己出去的边不能指向自己。
为了预防孤点(无边指向且无边指出),我在生成随机图时将边平均分到每个顶点中,如假设有100条边11个顶点,则每个顶点肯定有指出去的边9条,这样就很大概率上防止了孤点的存在。然后多余的1条边再随机分配给顶点。
2、残留网络则是通过当前流量数组间接计算得出,当前流量数组是个n*n数组,初始化将数组内容都设为0。当一条增广路径找到并计算出此路径的流量后,修改相对应的数组内的流量。然后残余流量就是将相对应的边流量减去当前流量得到。
3、对于节点的标注也是放到一个n*3的数组中。其中n表示节点总个数。第一列表示到达此节点的流量,第二列表示此节点的父节点,第三列表示流的方向(若是正向边流入则表示为1,若是为反向边则表示为-1)。初始化除了源点外的每个节点初始化的流量和方向均为0,父节点为-1。因为源点的特殊性所以将源点的父节点设为-2,以便和其他节点区分开。
以上是预处理部分,接下来就是算法的核心部分:如何查找增广路径及每次迭代的最小流量。
4、首先建立一个空队列,用于存放每次标记的节点。第一次将源点放入此队列中。以后取节点操作都是对队列进行。
5、每次都先取队列的第一个节点,然后开始从流数组中查看此节点指向哪些节点,若被指向的节点未被标记(父节点为0)且残余流量大于0,则将被指向的节点进行标记(第一列流量改为能通过的最小流量,第二列父节点改为刚刚取得的节点,第三列改为1表示是正向边)后放入队列。循环做此步直至当前节点所指向的点全部标记且入队列。
前向边获得最小流量是将当前边的总流量减当前流量,得到残余流量。若残余流量大于0,则与当前的最小流量比较,若小于最小流量则此残余流量设为最小流量。
6、将当前节点的前向边遍历结束后开始判断反向边(即是否有未标记的节点指向当前节点),若存在反向边则将流出流的节点进行标记(第一列流量改成最小流量,第二列父节点改成当前节点,第三列改成-1表示反向边)后放入队列。循环做此步直到所有反向边被遍历完毕。
反向边获得最小流量的方法与前向边不同,是直接判断此反向边的当前流量是否大于0,若是则当前流量与最小流量比,获得小的数作为最小流量。
7、每次遍历和标记完一个节点的所有前向边和后向边后,检查汇点是否被标记,若没被标记则继续取队列的下一个节点;若被标记则表示一条增广路径已被找到,此条路径上的所有当前流量都改为当前最小流量(即当前流量数