费用流:入门

最近看了一下费用流,找到适合模仿的程序对着资料看了一下,觉得比当初学的最大流还简单(当然现在与四个月以前的水平是不可同日而语了),基本思路是以费用为边权,用最短路算法找最小费用的增广路。主程序有点类似最大流的EK算法,而且找最小费用增光路基本上都是用SPFA来实现,也是相当熟悉的算法了。模仿了一个,又自己打了一个,第二个程序基本十二分钟就敲完了,不过两个程序都Debug了好久,都是变量打错或是漏掉语句的低级错误……

有空要研究一下最佳二分图匹配,zkw费用流之类的算法,再熟悉一下建模,参数做做线性规划与网络流24题吧,再找些经典的题目,基础的网络流应该不成问题了。

附最小费用流程序:

const
  oo=19930508;
var
  dist,path:array[0..1000] of longint;
  f,cost:array[0..1000,0..1000] of longint;
  i,j,k,m,n,x:longint;
  maxflow,mincost,flow:longint;
  q:array[0..100000] of longint;
  flag:array[0..10000] of boolean;
  head,tail:longint;
  now,pre:longint;
  s,t:longint;
  y,z,w:longint;
function min(a,b:longint):longint;
begin
  if a<b then exit(a) else exit(b);
end;



function spfa:boolean;
begin
  fillchar(flag,sizeof(flag),0);
  for i:=1 to n do
    dist[i]:=oo;
  head:=0;
  tail:=1;
  q[1]:=s;
  flag[s]:=true;
  dist[s]:=0;
  while head<tail do
  begin
    inc(head);
    i:=q[head];
    flag[i]:=false;
    for j:=1 to n do
      if (f[i,j]>0) and (dist[j]>dist[i]+cost[i,j]) then
      begin
        dist[j]:=dist[i]+cost[i,j];
        path[j]:=i;
        if not flag[j] then
        begin
          inc(tail);
          q[tail]:=j;
          flag[j]:=true;
        end;
      end;
  end;
  exit(dist[t]<>oo);
end;



procedure init;
begin
  readln(n,m);
  for i:=1 to n do
  begin
    for j:=1 to n do
      cost[i,j]:=oo;
    cost[i,i]:=0;
  end;
  for i:=1 to m do
  begin
    readln(x,y,z,w);
    f[x,y]:=z;
    cost[x,y]:=w;
  end;
  s:=1;
  t:=n;
end;

procedure main;
begin
  while spfa do
  begin
    now:=t;
    flow:=oo;
    while now<>s do
    begin
      pre:=path[now];
      flow:=min(flow,f[pre,now]);
      now:=pre;
    end;
    inc(maxflow,flow);
    now:=t;
    while now<>s do
    begin
      pre:=path[now];
      dec(f[pre,now],flow);
      inc(f[now,pre],flow);
      cost[now,pre]:=-cost[pre,now];
      mincost:=mincost+cost[pre,now]*flow;
      now:=pre;
    end;
  end;
end;

procedure print;
begin
  writeln(mincost);
end;

begin
  assign(input,'data.in');
  reset(input);
  assign(output,'data.out');
  rewrite(output);
  init;
  main;
  print;
  close(input);
  close(output);
end.


posted on 2011-05-23 22:49  oa414  阅读(660)  评论(0编辑  收藏  举报

导航