费用流:入门

最近看了一下费用流,找到适合模仿的程序对着资料看了一下,觉得比当初学的最大流还简单(当然现在与四个月以前的水平是不可同日而语了),基本思路是以费用为边权,用最短路算法找最小费用的增广路。主程序有点类似最大流的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.





你可能感兴趣的:(入门)