www.gusucode.com > 里面有最大流,最小费用最大流和着色问题的matlab程序和lingo程序 > 里面有最大流,最小费用最大流和着色问题的matlab程序和lingo程序/最大流,最小费用流,着色程序/min_max最小费用流.m
function [f,m,fb]=min_max(C,b,f0) %最小代价的负回路算法 %思想:保持流值不变而逐步减少代价 % 求给定流值m的流f。(1--> n) %给出流值m的初始流f0,如果m不是最大流,可以通过调低边容量的方法用最大流程序得到初始流 %所以假定初始流f0已知 %C=[0 15 16 0 0 %0 0 0 13 14 %0 11 0 17 0 %0 0 0 0 8 %0 0 0 0 0];%容量网络 %b=[0 4 1 0 0 % 0 0 0 6 1 % 0 2 0 3 0 % 0 0 0 0 2 % 0 0 0 0 0];%费用网络 f=f0; n=length(C);finish=0;q=0; while(finish~=n&q>=0)%找到负回路调整流以后重新开始,如果顶点n搜索完毕没有找到负回路,结束 Nf=C-f;Nf=Nf+f';%流量的伴随网络,随着流的调整在改变 Nb=b-b'; for i=1:n%流量对应费用的伴随网络,随着流的调整在改变 for j=1:n if Nf(i,j)==0 Nb(i,j)=0; end end end for i=1:n%作为起点开始搜索包含这个顶点的回路 flag1=1;%有负回路需要跳到最外层while使用 finish=n; T=i;%用于搜索还没有归入R的子顶点 R=[];%当前点以前被搜索过的点 L=[];%标号用于判断是不是回路并确定回路 while(flag1)%如果当前生长点有多个子顶点 T_R=setdiff(T,R);s=length(T_R); if s==0%没有向后有流量的路了,改变起点 break;%跳到外层for end u=T_R(1);%往后搜索有多个生长点取第一个 while(1)%向后搜索 Tc=setdiff(1:n,T);Tc=union(Tc,i);%可以搜索i for k=1:length(Tc) flag=1;%如果找不到后继顶点,将作为返回的标记 v=Tc(k); if Nf(u,v)>0 flag=0;%找到了后继顶点 T=union(T,v); L(v)=u; if v==i m=i;t=-m;%先暂时赋值不会等于i的数 q=0;ff=inf; while(t~=i) %逆向追踪求i-->i的圈 t=L(m); q=q+Nb(t,m);%回路上的费用和,判断是不是负回路 ff=min(ff,Nf(t,m)); m=t; end if q<0%是负回路 m=i;t=-m; while(t~=i) %修改流量 t=L(m); if f(m,t)>0%(t,m)的反方向有流,退回去 f(m,t)=f(m,t)-ff; else f(t,m)=f(t,m)+ff;%(t,m)方向有流或两方向都是零流 end m=t; end flag=1;flag1=0; break;%跳到最外层的while进行循环 else%不是负回路 T=setdiff(T,i);%不能走向i,退出来找下一个子顶点 end end end end%内层for结束 if flag%找不到后继顶点, 跳到第二层while换顶点(不是起点)搜索 R=union(R,u); break; end end%第三个while结束 end%第二个while结束 if flag1==0 break; end end%for结束 end%第一个while结束 m=0; for j=1:n m=m+f(1,j);%求总流量 fb=sum(sum(b.*f));%求总费用 end