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

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

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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值