美文网首页
【数学建模算法】(13)图的应用:最大流算法(下)

【数学建模算法】(13)图的应用:最大流算法(下)

作者: 热爱学习的高老板 | 来源:发表于2019-08-15 15:56 被阅读0次

3.最大流的一种算法——标号法

标号法是由 Ford 和 Fulkerson 在 1957 年提出的。用标号法寻求网络中最大流的基本思想是寻找可增广轨,使网络的流量得到增加,直到最大为止。即首先给出一个初始流,这样的流是存在的,例如零流。如果存在关于它的可增广轨,那么调整该轨上每条弧上的流量,就可以得到新的流。对于新的流,如果仍存在可增广轨,则用同样的方法使流的值增大,继续这个过程,直到网络中不存在关于新得到流的可增广轨为止,则该流就是所求的最大流。

这个方法分为以下两个过程:
A.标号过程:通过标号过程寻找一条可増广轨。
B.增流过程:沿着可増广轨增加网络的流量。

3.1.标号过程

1.给发点标号为\left(s^{+}, \infty\right)

2.若顶点x已标号,则对x所有未标号的邻接顶点y按如下规则标号:

(1)若(x, y) \in A,且f_{x y}<u_{x y}时,令\delta_{y}=\min \left\{u_{x y}-f_{x y}, \delta_{x}\right\},则给顶点y标号为\left(x^{+}, \delta_{y}\right),若f_{x y}=u_{x y},则不给顶点y标号。

笔者认为这一步的意思是对流量未达到容量的流进行标号。

(2)(y, x) \in A,且f_{y x}>0,令\delta_{y}=\min \left\{f_{y x}, \delta_{x}\right\}则给y标号为\left(x^{-}, \delta_{y}\right),若f_{y x}=0,则不给y标号。

力求让反向流量都为0。

3.不断重复步骤(2)直到收点t被标号,或不再有顶点可以标号为止。当t被标号时,表明存在一条从st的可増广轨,则转向下面的增流过程。如果t点不能被标号,且不存在其他可以标号的顶点时,表明不存在从st的増广轨,算法结束,此时所得的流就是最大流。

只要标过号的顶点,都有待优化的流,都要放到下面的增流过程中进行优化。

3.2.增流过程

1.令u=t

从起点开始

2.若u的标号\left(v^{+}, \delta_{t}\right),则f_{w}=f_{w}+\delta_{i}

正向流,流量加满

u的标号\left(v^{-}, \delta_{t}\right),则
f_{u v}=f_{u v}-\delta_{t}

反向流,流量清空

3.若u=s,则去掉全部标号,并回到标号过程。否则令u=v,并回到增流过程2。

如果到了终点,则这条轨调整完成,返回标下一条轨,若没到终点,则以下一个起点开始继续增流。

3.3.程序设计具体步骤

对于每个节点,标号包括两部分信息
(\text { pred }(j), \max f(j))
该节点在可能的增广路中的一个节点\operatorname{pred}(j),以及沿该可能的增广路到该节点为止。可以增广的最大流量\max \mathrm{f}(j)

1.置初始可行流x(如零流);对节点t标号,即令\max \mathrm{f}(t)=任意正值(如1)。
2.若\max \mathrm{f}(t)>0,继续下一步;否则停止,已经得到最大流,结束。
3.取消所有节点j \in V的标号,即令\max \mathrm{f}(j)=0\operatorname{pred}(j)=0;令LIST =\{s\},对节点s标号,即令\max \mathrm{f}(s)=充分大的正值。
4.如果LIST \neq \Phi\max \mathrm{f}(t)=0继续下一步,否则:

(1)如果t已有标号(即\max \mathrm{f}(t)>0),则找到了一条增増广路,沿该増广路对流x进行増广(增广的流量即是\max \mathrm{f}(t),増广路可以根据pred方便地回溯得到),转到2
(2)如果t没有标号(即\mathrm{LIST}=\Phi\max \mathrm{f}(t)=0),则停止,已得到最大流。

5.从LIST中移走一个节点i;寻找从节点i出发的所有可能的増广弧;
(1)对非饱和前向弧(i,j),若节点j没有标号(即\operatorname{pred}(j)=0),对j进行标号,即令
\max \mathrm{f}(j)=\min \left\{\max \mathrm{f}(i), u_{i j}-x_{i j}\right\}, \quad \operatorname{pred}(j)=i
并将j加入LIST中。
(2)对非空后向弧(j,i),若节点j没有标号(即\operatorname{pred}(j)=0),对j进行标号,即令
\max \mathrm{f}(j)=\min \left\{\max \mathrm{f}(i), x_{i j}\right\}, \quad \operatorname{pred}(j)=-i
并将j加入LIST中。

3.4.举例

例1 计算最大流,弧上两个数字分别代表容量和当前流量。

例1题图

编写Matlab程序:

clc,clear
u(1,2)=1;u(1,3)=1;u(1,4)=2;u(2,3)=1;u(2,5)=2;
u(3,5)=1;u(4,3)=3;u(4,5)=3;
f(1,2)=1;f(1,3)=0;f(1,4)=1;f(2,3)=0;f(2,5)=1;
f(3,5)=1;f(4,3)=1;f(4,5)=0;
n=length(u);list=[];maxf(n)=1;
while maxf(n)>0
    maxf=zeros(1,n);pred=zeros(1,n);
    list=1;record=list;maxf(1)=inf;
    %list是未检查邻接点的标号点,record是已标号点
    while (~isempty(list))&(maxf(n)==0)
        flag=list(1);list(1)=[];
        label1= find(u(flag,:)-f(flag,:));
        label1=setdiff(label1,record);
        list=union(list,label1);
        pred(label1)=flag;
        maxf(label1)=min(maxf(flag),u(flag,label1)...
        -f(flag,label1));
        record=union(record,label1);
        label2=find(f(:,flag));
        label2=label2';
        label2=setdiff(label2,record);
        list=union(list,label2);
        pred(label2)=-flag;
        maxf(label2)=min(maxf(flag),f(label2,flag));
        record=union(record,label2);
    end
        if maxf(n)>0
            v2=n; v1=pred(v2);
            while v2~=1
            if v1>0
                f(v1,v2)=f(v1,v2)+maxf(n);
            else
                v1=abs(v1);
                f(v2,v1)=f(v2,v1)-maxf(n);
            end
        v2=v1; v1=pred(v2);
            end
    end
end
f

当然,最大流问题也可以从线性规划的角度解决:

例2 现需要将城市s的石油通过管道运送到城市t,中间有4个中转站v_{1}, v_{2}, v_{3}v_{4},城市与中转站的连接以及管道的容量如图所示,求从城市st的最大流。

例2图

提供两个版本的Lingo程序:

model:
sets:
nodes/s,1,2,3,4,t/;
arcs(nodes,nodes)/s 1,s 3,1 2,1 3,2 3,2 t,3 4,4 2,4 t/:c,f;
endsets
data:
c=8 7 9 5 2 5 9 6 10;
enddata
n=@size(nodes); !顶点的个数;
max=flow;
@for(nodes(i)|i #ne#1 #and# i #ne# n:
@sum(arcs(i,j):f(i,j))=@sum(arcs(j,i):f(j,i)));
@sum(arcs(i,j)|i #eq# 1:f(i,j))=flow;
@sum(arcs(i,j)|j #eq# n:f(i,j))=flow;
@for(arcs:@bnd(0,f,c));
end
model:
sets:
nodes/s,1,2,3,4,t/;
arcs(nodes,nodes):c,f;
endsets
data:
c=0;
@text('fdata.txt')=f;
enddata
calc:
c(1,2)=8;c(1,4)=7;
c(2,3)=9;c(2,4)=5;
c(3,4)=2;c(3,6)=5;
c(4,5)=9;c(5,3)=6;c(5,6)=10;
endcalc
n=@size(nodes); !顶点的个数;
max=flow;
@for(nodes(i)|i #ne#1 #and# i #ne# n:
@sum(nodes(j):f(i,j))=@sum(nodes(j):f(j,i)));
@sum(nodes(i):f(1,i))=flow;
@sum(nodes(i):f(i,n))=flow;
@for(arcs:@bnd(0,f,c));
end

相关文章

网友评论

      本文标题:【数学建模算法】(13)图的应用:最大流算法(下)

      本文链接:https://www.haomeiwen.com/subject/fqwajctx.html