最小费用最大流

来源:互联网 发布:端口号是什么 编辑:程序博客网 时间:2024/04/29 11:24

介绍:

“流”的问题可能不仅仅是流量,还包括“费用”的因素。网络的每一条边(Vi,Vj)除给定了容量Cij外,还给了一个单位流量费用Bij>=0。问题的数学模型是求最大流F,使流的总输送费用B(F)=∑Bij  Fij (I,j∈A)取极小值。这就是所谓的最小费用最大流问题。

下图所示是一个公路网,s是仓库所在地,t是物资终点。每一条边都有两个数字,第一个数字表示某段时间通过公路的物资的最多吨数,第二个数字表示每顿物资通过该公路的费用。问怎样安排才能即使得从s运到t的物资最多,又使得总的运输费用最少?



算法思想:

从F=0开始,设已知F是流量V(F)的最小费用流,余下的问题是如何去寻求关于F的最小费用可增广路径。

构造一个加权有向图W(F),它的节点是原网络D的节点,把D中的每一条边(Vi,Vj)变成两个方向相反的边<Vi,Vj>和<Vj,Vi>。定义W(F)中的边权Wij为


于是在网络中寻求关于F的最小费用可增广路径,等价于在加权有向图W(F)中寻求从Vs到Vt的最短路径。




    

             


   


          


              



           





模板:

program mincost;
const
  maxn=1000;
  maxm=1000*1000*2;
type
  edge=record
    u,v,r,c,next,op:longint;
  end;
var
  g:array[1..maxm] of edge;
  h:array[1..maxn] of longint;
  s,t,flow,cost,a,b,c,d,tot,n,m,i:longint;


procedure add(u,v,r,c:longint);
begin
  inc(tot);
  g[tot].u:=u;
  g[tot].v:=v;
  g[tot].r:=r;
  g[tot].c:=c;
  g[tot].next:=h[u];
  h[u]:=tot;
  g[tot].op:=tot+1;
  inc(tot);
  g[tot].u:=v;
  g[tot].v:=u;
  g[tot].r:=0;
  g[tot].c:=-c;
  g[tot].next:=h[v];
  h[v]:=tot;
  g[tot].op:=tot-1;
end;


function spfa(s,t:longint;var flow,cost:longint):boolean;
var
  d,p,a:array[1..maxn] of longint;
  inq:array[1..maxn] of boolean;
  q:array[1..maxm] of longint;
  i,u,v,tmp,f,r:longint;
begin
  fillchar(d,sizeof(d),$7f);
  fillchar(inq,sizeof(inq),false);
  d[s]:=0;  inq[s]:=true;  p[s]:=0;
  a[s]:=maxlongint;
  f:=1;  r:=1;  q[f]:=1;
  repeat
    u:=q[f];    tmp:=h[u];
    while tmp<>-1 do
      begin
        v:=g[tmp].v;
        if (g[tmp].r>0) and (d[v]>d[u]+g[tmp].c) then
          begin
            d[v]:=d[u]+g[tmp].c;
            p[v]:=tmp;
            a[v]:=min(a[u],g[tmp].r);
            if not inq[u] then
              begin
                inc(r); q[r]:=u; inq[u]:=true;
              end;
          end;
        tmp:=g[tmp].next;
      end;
    inc(f);
    inq[u]:=false;
  until f>r;
  if d[t]=maxlongint then exit(false);
  flow:=flow+a[t];
  cost:=cost+d[t]*a[t];
  u:=t;
  while (u<>s)do
    begin
      g[p[u]].r:=g[p[u]].r-a[t];
      g[g[p[u]].op].r:=g[g[p[u]].op].r+a[t];
      u:=g[p[u]].u;
    end;
  exit(true);
end;


begin
  fillchar(h,sizeof(h),$ff);
  readln(n,m);
  for i:=1 to m do
    begin
      readln(a,b,c,d);
      add(a,b,c,d);
    end;
  flow:=0;
  cost:=0;
  s:=1;
  t:=n;
  while spfa(s,t,flow,cost) do;
  writeln(flow,' ',cost);
end.


习题:

poj 2135 Farm Tour

poj 2159

poj 2175 Evacuation Plan

poj 3686 The Windy’s

poj 3068 “Shortest”pair of paths

poj 2195 Going Home

poj 3422 Kaka’s Matrix Travels

poj 2516


具体详见:http://download.csdn.net/download/boyxiejunboy/8911065(不用积分下载哦)

1 0