用MATLAB求解最大流问题

用MATLAB求解最大流问题,第1张

function [f,wf,No]=MaxFlowMinCut_Me(n,C)

% 利用Ford--Fulkerson 标号法求最大流算法的MATLAB 程序代码

% f %显示最大流

% wf %显示最大流量

% No %显示标号, 由此可此芹悄得最小割

% n 节点个数

% C %弧容量

% Example:

% n=8

% C=[0 5 4 3 0 0 0 0

%0 0 0 0 5 3 0 0

%0 0 0 0 0 3 2 0

%0 0 0 0 0 0 2 0

%0 0 0 0 0 0 0 4

%0 0 0 0 0 0 0 3

%0 0 0 0 0 0 0 5

%0 0 0 0 0 0 0 0]

% [f,wf,No]=MaxFlowMinCut_Me(n,C)

for(i=1:n)for(j=1:n)f(i,j)=0endend %取初始可行流f 为零流

for(i=1:n)No(i)=0d(i)=0end %No,d 记录标号

while(1)

No(1)=n+1d(1)=Inf%给发点vs 标号

while(1)pd=1%标号过程

for(i=1:n)if(No(i)) %选择一个已标号的点vi

for(j=1:n)if(No(j)==0&f(i,j)<C(i,j)) %对于未给标号森渣的点vj, 当vivj 为首禅非饱和弧时

No(j)=id(j)=C(i,j)-f(i,j)pd=0

if(d(j)>d(i))d(j)=d(i)end

elseif(No(j)==0&f(j,i)>0) %对于未给标号的点vj, 当vjvi 为非零流弧时

No(j)=-id(j)=f(j,i)pd=0

if(d(j)>d(i))d(j)=d(i)endendendendend

if(No(n)|pd)breakendend %若收点vt 得到标号或者无法标号, 终止标号过程

if(pd)breakend %vt 未得到标号, f 已是最大流, 算法终止

dvt=d(n)t=n%进入调整过程, dvt 表示调整量

while(1)

if(No(t)>0)f(No(t),t)=f(No(t),t)+dvt%前向弧调整

elseif(No(t)<0)f(No(t),t)=f(No(t),t)-dvtend %后向弧调整

if(No(t)==1)for(i=1:n)No(i)=0d(i)=0endbreakend %当t 的标号为vs 时, 终止调整过程

t=No(t)endend%继续调整前一段弧上的流f

wf=0for(j=1:n)wf=wf+f(1,j)end

end

现在给的这段程序是网上的,我也没跑,先把网址给你,希望对你有帮助!

http://bbs.elecfans.com/jishu_207409_1_1.html

程序:

function [f,MinCost,MaxFlow]=MinimumCostFlow(a,c,V,s,t)

%% MinimumCostFlow.m

% 最小费用最大流算法通用Matlab函悄野数

%% 基于Floyd最短路算法的Ford和Fulkerson迭加算法

% GreenSim团队原创作品,转载请注明

%% 输入参数列表

% a单位流量的费用矩启拿喊阵

% c链路容量矩阵

% V最大流的预设值,可为无穷大

% s源节点

% t目的节点

%% 输出参数列表

% f链路流量矩阵

% MinCost 最小费用

% MaxFlow 最大流量

%% 第一步:初始化

N=size(a,1)%节点数目

f=zeros(N,N)%流量矩阵,初始时为零流

MaxFlow=sum(f(s,:))%最大流量,初始时也为零

flag=zeros(N,N)%真实的前向边应该被记住

for i=1:N

for j=1:N

if i~=j&&c(i,j)~=0

flag(i,j)=1%前向边标记

flag(j,i)=-1%反向边标记

end

if a(i,j)==inf

a(i,j)=BV

w(i,j)=BV%为提高程序的稳健性,以一个有限大数取代无穷大

end

end

end

if L(end)<BV

RE=1%如果路径长度小于大数,说明路径存在

else

RE=0

end

%% 第二步:迭代过程

while RE==1&&MaxFlow<=V%停止条件为达到最大流的预设值或者没有从s到t的最短路

%以下为更新网络结构

MinCost1=sum(sum(f.*a))

MaxFlow1=sum(f(s,:))

f1=f

TS=length(R)-1%路径经过的跳数

LY=zeros(1,TS)%流量裕度

for i=1:TS

LY(i)=c(R(i),R(i+1))

end

maxLY=min(LY)%流量裕度的最小值,也即最大能够增加的流量

for i=1:TS

u=R(i)

v=R(i+1)

if flag(u,v)==1&&maxLY<c(u,v)%当这条边为前向边且是非饱和边时

f(u,v)=f(u,v)+maxLY%记录流量值

w(u,v)=a(u,v)%更新权重值

c(v,u)=c(v,u)+maxLY%反向链路的流量裕度更新

elseif flag(u,v)==1&&maxLY==c(u,v)%当这条边为前向边且是饱和边时

w(u,v)=BV%更新权重值

c(u,v)=c(u,v)-maxLY%更新流量裕度值

w(v,u)=-a(u,v)%反向链敏尘路权重更新

elseif flag(u,v)==-1&&maxLY<c(u,v)%当这条边为反向边且是非饱和边时

w(v,u)=a(v,u)

c(v,u)=c(v,u)+maxLY

w(u,v)=-a(v,u)

elseif flag(u,v)==-1&&maxLY==c(u,v)%当这条边为反向边且是饱和边时

w(v,u)=a(v,u)

c(u,v)=c(u,v)-maxLY

w(u,v)=BV

else

end

end

MaxFlow2=sum(f(s,:))

MinCost2=sum(sum(f.*a))

if MaxFlow2<=V

MaxFlow=MaxFlow2

MinCost=MinCost2

[L,R]=FLOYD(w,s,t)

else

f=f1+prop*(f-f1)

MaxFlow=V

MinCost=MinCost1+prop*(MinCost2-MinCost1)

return

end

if L(end)<BV

RE=1%如果路径长度小于大数,说明路径存在

else

RE=0

end

end

function [L,R]=FLOYD(w,s,t)

n=size(w,1)

D=w

path=zeros(n,n)

%以下是标准floyd算法

for i=1:n

for j=1:n

if D(i,j)~=inf

path(i,j)=j

end

end

end

for k=1:n

for i=1:n

for j=1:n

if D(i,k)+D(k,j)<D(i,j)

D(i,j)=D(i,k)+D(k,j)

path(i,j)=path(i,k)

end

end

end

end

L=zeros(0,0)

R=s

while 1

if s==t

L=fliplr(L)

L=[0,L]

return

end

L=[L,D(s,t)]

R=[R,path(s,t)]

s=path(s,t)

end


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12326893.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-22
下一篇2023-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存