费用流:邻接表实现

虽然说最小费用流10分钟就能敲出来,可是只是练习过裸的邻接矩阵实现。曾经考虑过用邻接表实现,尝试写过方格取数,未果,今日翻出来,发现bug一堆。今天写POJ2315,然后纠结了一个多小时,80%时间都在debug,最后发现是一些低级错误+邻接表的实现错误。

总的来说,邻接表需要存储prev和prevEdge数组,分别记录当前节点的前驱节点和连向当前节点的边在数组中的位置,前者用来往前找,判断有没有到源点,后者用来求增广路的流量、更新流量。

本题做法参考了http://www.cnblogs.com/ylfdrib/archive/2010/08/05/1792735.html

题意简单:FJ有N个农场,M条路,FJ要领朋友游玩,从1走到N,再回到1,不走重复路,每条路长度不一样,问最短路长为多少。

转化为最小费用流来求解,建一源点S,指向节点1,容量为2,距离0,建一汇点T,N节点指向汇点,容量为2,距离为0,表示要有两条路从S到T,其余给定的路,容量为1,边权为路长,表示每条路只走一次。

另外一些低级错误有变量名打错等,还有函数中数组开太大导致堆栈溢出,另外oo的值设的有点小。

网络流中经常要用到常量oo(INF,无限)来表示maxlongint,直接用maxlongint会溢出的,然后我就参考看过的一个程序,设为一个生日,一千多万不小了,不过这题还不行,后面要加个零。我用的是谁的生日呢?自然不是我的,只是隐约在别人谈话中听到可能是她的生日,然后从此这个数字就几乎出现在我的每一个程序间了。

附POJ2315程序:

const

  oo=199305080;

var

  pre,preedge,g,next,c,e,cost,opp:Array[0..1000000] of longint;

  maxflow,p,i,j,k,m,n,mincost,flow,now,x,y,z,size,s,t:longint;





procedure addedge(x,y,z,w:longint);

begin

  inc(size);

  e[size]:=y;

  c[size]:=z;

  cost[size]:=w;

  opp[size]:=size+1;

  next[size]:=g[x];

  g[x]:=size;



  inc(size);

  e[size]:=x;

  c[size]:=0;

  cost[size]:=-w;

  next[size]:=g[y];

  g[y]:=size;

  opp[size]:=size-1;

end;





function spfa:boolean;

var

  q,dist:array[0..10000] of longint;

  flag:array[0..10000] of boolean;

  head,tail,i,j,p:longint;

begin

  head:=0;

  tail:=1;

  q[1]:=s;

  for i:=1 to t do

    dist[i]:=oo;

  dist[s]:=0;

  fillchar(flag,sizeof(flag),0);

  flag[s]:=true;

  while head<tail do

  begin

    inc(head);

    i:=q[head];

    flag[i]:=false;

    p:=g[i];

    while p<>0 do

    begin

      j:=e[p];

      if (dist[j]>dist[i]+cost[p])and(c[p]>0) then

      begin

        dist[j]:=dist[i]+cost[p];

        pre[j]:=i;

        preedge[j]:=p;

        if not flag[j] then

        begin

          inc(tail);

          q[tail]:=j;

          flag[j]:=true;

        end;

      end;

      p:=next[p];

    end;

  end;

  exit(dist[t]<>oo);

end;







procedure init;

begin

  readln(n,m);

  fillchar(g,sizeof(g),0);

  for i:=1 to m do

  begin

    readln(x,y,z);

    addedge(x,y,1,z);

    addedge(y,x,1,z);

  end;

  s:=n+1;

  t:=n+2;

  addedge(s,1,2,0);

  addedge(n,t,2,0);

end;



function min(a,b:longint):longint;

begin

  if a<b then exit(a) else exit(b);

end;





procedure main;

begin

  while spfa do

  begin

    now:=t;

    flow:=oo;

    while now<>s do

    begin

      flow:=min(flow,c[preedge[now]]);

      now:=pre[now];

    end;

    now:=t;

    while now<>s do

    begin

      p:=preedge[now];

      dec(c[p],flow);

      inc(c[opp[p]],flow);

      mincost:=mincost+cost[p]*flow;

      now:=pre[now];

    end;

  end;

end;



procedure print;

begin

  writeln(mincost);

end;





begin



  init;

  main;

  print;

end.



你可能感兴趣的:(实现)