网络流的征程——最小费用最大流

来源:互联网 发布:linux下如何awk 编辑:程序博客网 时间:2024/05/15 20:04

这类模板要求在所有的最大流中找出总费用最小的流量,最后输出费用。

思路:其实这类模板就是用最短路径找增广路,具体可见程序:

type  edge=record        tt,vol,cost,next:longint;       end;const  INF=maxlongint shr 2;var  q,a,pre,pos,dis:array[0..100000]of longint;  e:array[0..200000]of edge;  cost,flow,x,y,z,n,m,i,f,cnt,start,stop:longint;  vis:array[0..100000]of boolean;function spfa(s,t:longint):boolean;var  head,tail,now,i,adj:longint;begin  fillchar(pre,sizeof(pre),$ff);  fillchar(vis,sizeof(vis),0);  head:=0;tail:=1;  fillchar(dis,sizeof(dis),$7f shr 2);  q[tail]:=s;  pre[s]:=s;  dis[s]:=0;  vis[s]:=true;  while head<>tail do   begin     head:=head+1;     now:=q[head];     vis[now]:=false;     i:=a[i];     while i>0 do      begin        adj:=e[i].tt;        if (e[i].vol>0)and(dis[now]+e[i].cost<dis[adj]) then         begin           dis[adj]:=dis[now]+e[i].cost;           pre[adj]:=now;           pos[adj]:=i;           if not vis[adj] then            begin              vis[adj]:=true;              tail:=tail+1;              q[tail]:=adj;            end;         end;        i:=e[i].next;      end;   end;   exit(pre[t]>-1);end;procedure insert(from,tt,vol,cost:longint);begin  cnt:=cnt+1;  e[cnt].tt:=tt;  e[cnt].vol:=vol;  e[cnt].cost:=cost;  e[cnt].next:=a[from];  a[from]:=cnt;end;begin  readln(n,m);  for i:=1 to m do   begin     readln(x,y,z,cost);     insert(x,y,z,cost);     insert(y,x,0,-cost);   end;  readln(start,stop);  cost:=0;flow:=0;  while spfa(start,stop) do   begin     f:=INF;     i:=stop;     while i<>start do      begin        if (e[pos[i]].vol<f) then         f:=e[pos[i]].vol;        i:=pre[i];      end;     flow:=flow+f;     cost:=cost+dis[stop]*f;     i:=stop;     while i<>start do      begin        e[pos[i]].vol:=e[pos[i]].vol-f;        inc(e[pos[i]xor 1].vol,f);      end;   end;  write(cost);end.


0 0
原创粉丝点击