zoukankan      html  css  js  c++  java
  • 算法模板——Dinic最小费用最大流

    实现功能:输入M,N,S,T;接下来M行输入M条弧的信息(包括起点,终点,流量,单位费用);实现功能是求出以S为源点,T为汇点的网络最大流的最小费用

    其实相当的像Dinic最大流呐= =

    还是spfa处理出最短路径(注意,这次是最短路径,所以时空复杂度将有所提高,害得我都开循环队列了TT),然后顺着最短路径顺藤摸瓜找回去,求出流大小和最小的费用,然后,没有然后了,程序还是一样的好懂么么哒(HansBug:感觉Dinic算法真心超级喜感,为啥我之前就没发现呢= =,还有鸣谢wnjxyk神犇提供的C++模板么么哒 Wnjxyk:^_^)

    (本程序为BZOJ1927的AC程序,模板题么么哒,还有其实感觉spfa函数里面每次清空e数组貌似不是很必要,但还是图个安心写下吧)

     1 const maxl=100000;
     2 type
     3     point=^node;
     4     node=record
     5                g,w,f:longint;
     6                next,anti:point;
     7     end;
     8 var
     9    a,e:array[0..10000] of point;
    10    i,j,k,l,m,n,s,t,ans,flow:longint;
    11    c,g:array[0..10000] of longint;
    12    d:array[0..maxl] of longint;
    13 function min(x,y:longint):longint;
    14          begin
    15               if x<y then min:=x else min:=y;
    16          end;
    17 procedure swap(var x,y:longint);
    18           var z:longint;
    19           begin
    20                z:=x;x:=y;y:=z;
    21           end;
    22 procedure add(x,y,z,t:longint);
    23           var p:point;
    24           begin
    25                new(p);p^.g:=y;p^.w:=z;p^.f:=t;p^.next:=a[x];a[x]:=p;
    26                new(p);p^.g:=x;p^.w:=0;p^.f:=-t;p^.next:=a[y];a[Y]:=p;
    27                a[x]^.anti:=a[y];a[y]^.anti:=a[x];
    28           end;
    29 function spfa:boolean;     //神(dou)奇(bi)的最短路径预处理
    30          var f,r:longint;p:point;
    31          begin
    32               for i:=s to t do c[i]:=maxlongint;
    33               for i:=s to t do e[i]:=nil;
    34               d[1]:=s;f:=1;r:=2;g[s]:=1;c[s]:=0;
    35               while f<>r do
    36                     begin
    37                          p:=a[d[f]];
    38                          while p<>nil do
    39                                begin
    40                                     if (p^.w<>0) and (c[p^.g]>(c[d[f]]+p^.f)) then
    41                                        begin
    42                                             c[p^.g]:=c[d[f]]+p^.f;
    43                                             e[p^.g]:=p;
    44                                             if g[p^.g]=0 then
    45                                                begin
    46                                                     g[p^.g]:=1;
    47                                                     d[r]:=p^.g;r:=(r mod maxl)+1;
    48                                                end;
    49                                        end;
    50                                     p:=p^.next;
    51                                end;
    52                          g[d[f]]:=0;f:=(f mod maxl)+1;
    53                     end;
    54               exit(c[t]<>maxlongint);
    55          end;
    56 procedure calc;
    57           begin
    58                l:=maxlongint;
    59                i:=t;
    60                while i<>s do
    61                      begin
    62                           l:=min(l,e[i]^.w);
    63                           i:=e[i]^.anti^.g;   //当前弧的反向弧所指向的点就是你要回到的点^_^
    64                      end;
    65                i:=t;inc(flow,l);
    66                while i<>s do
    67                      begin
    68                           if e[i]^.w<>maxlongint then dec(e[i]^.w,l);
    69                           if e[i]^.anti^.w<>maxlongint then inc(e[i]^.anti^.w,l);
    70                           inc(ans,e[i]^.f*l);
    71                           i:=e[i]^.anti^.g;
    72                      end;
    73           end;
    74 begin
    75      readln(n,m);s:=0;t:=2*n+1;
    76      for s:=0 to t do a[i]:=nil;
    77      for i:=1 to n do
    78          begin
    79               read(l);
    80               add(0,i,1,0);
    81               add(i+n,t,1,0);
    82               add(0,i+n,1,l);
    83          end;
    84      readln;
    85      for i:=1 to m do
    86          begin
    87               readln(j,k,l);
    88               if j>k then swap(j,k);
    89               add(j,k+n,1,l);
    90          end;
    91      flow:=0;ans:=0; //flow表示最大流;ans表示最小费用
    92      while spfa do calc;
    93      writeln(ans);
    94      readln;
    95 end.

     

  • 相关阅读:
    第七讲 宋词:婉约之曲与豪放之声
    P2024 食物链
    可以吹一年的事
    信息传递
    11.11模拟赛总结(又名斗地主战记)
    11.9模拟赛总结
    扩展欧几里得(exgcd模板)
    发糖果(拓扑排序模板)
    高斯消元
    关于我
  • 原文地址:https://www.cnblogs.com/HansBug/p/4439979.html
Copyright © 2011-2022 走看看