费用流:邻接表实现
虽然说最小费用流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.