• 最小/大费用最大流模板(codevs1914)


         void addedge(int fr,int to,int cap,int cos){
             sid[cnt].fr=fr;sid[cnt].des=to;sid[cnt].cap=cap;sid[cnt].cos=cos;sid[cnt].next=nd[fr];nd[fr]=cnt++;
             sid[cnt].fr=to;sid[cnt].des=fr;sid[cnt].cap=0;sid[cnt].cos=-cos;sid[cnt].next=nd[to];nd[to]=cnt++;
         }
         
        int spfa(){
            dl[head=tail=1]=sor;
            for (int i=1;i<=n+2;i++) dis[i]=1e9;
            for (int i=0;i<=n+2;i++) b[i]=0;
            for (int i=0;i<=n+2;i++) count[i]=0;
            b[sor]=1;
            dis[sor]=0;
            while (head<=tail){
                for (int p=nd[dl[head]];p!=-1;p=sid[p].next)
                    if ((sid[p].cap!=0)&&(dis[sid[p].des]>dis[dl[head]]+sid[p].cos)){
                        path[sid[p].des]=p;
                        if (b[sid[p].des]==0){
                            dl[++tail]=sid[p].des;
                            b[sid[p].des]=1;
                            count[sid[p].des]++;
                        }
                        dis[sid[p].des]=dis[dl[head]]+sid[p].cos;
                    }
                    b[dl[head++]]=0;        
            }
            
            if (dis[tar]==1e9) return(0);else return(1);
        }
        
        void aug(){
            int po=tar,flow=1e9;
    
            while (po!=sor){
                int p=path[po];
                flow=min(flow,sid[p].cap);
                po=sid[p].fr;
            }
                
            po=tar;
            
            while (po!=sor){
                int p=path[po];
                sid[p].cap-=flow;
                ans+=flow*sid[p].cos;
                sid[p^1].cap+=flow;
                po=sid[p].fr;
            }
        }

    最小费用最大流

    uses math;
    
    var
     n,m,i,j :longint;
     ans:int64;
     dl:array[1..50000] of longint;
     cost,tcap,cap:array[0..501,0..501] of int64;
     dis:array[0..501] of longint;
     pre:array[0..501] of longint;
     a,b:array[1..250] of longint;
     c:Array[1..250,1..250] of longint;
    
     procedure build;
     var
      i,j:longint;
       begin
         for i:=1 to n do
           begin
             cap[0,i]:=maxlongint;
             cost[0,i]:=0;
           end;
    
         for i:=1 to n do
           begin
             cap[i,i+n]:=a[i];
             cost[i,i+n]:=0;
           end;
    
         for i:=1 to n do
           for j:=1 to m do
             begin
               cap[i+n,j+2*n]:=maxlongint;
               cost[i+n,j+2*n]:=c[i,j];
               cost[j+2*n,i+n]:=-c[i,j];
             end;
    
         for i:=1 to m do
           begin
             cap[i+2*n,i+2*n+m]:=b[i];
             cost[i+2*n,i+2*n+m]:=0;
           end;
    
         for i:=1 to m do
           begin
             cap[i+2*n+m,2*n+2*m+1]:=maxlongint;
             cost[i+2*n+m,2*n+2*m+1]:=0;
           end;
       end;
    
      procedure aug;
      var
       po:longint;
       mi:int64;
       pr:longint;
        begin
          po:=2*n+2*m+1;
          mi:=maxlongint;
          while po<>0 do
            begin
              pr:=pre[po];
              mi:=min(mi,tcap[pr,po]);
              po:=pr;
            end;
    
          po:=2*n+2*m+1;
          while po<>0 do
            begin
              pr:=pre[po];
              dec(tcap[pr,po],mi);
              inc(tcap[po,pr],mi);
              inc(ans,mi*cost[pr,po]);
              po:=pr;
            end;
        end;
    
      function spfa1:boolean;
      var
       i,head,tail,u:longint;
        begin
          for i:=1 to 2*m+2*n+1 do
             dis[i]:=maxlongint;
          dis[0]:=0;
    
          head:=1;tail:=1;
          dl[1]:=0;
          while head<=tail do
            begin
              u:=dl[head];
              for i:=0 to 2*n+2*m+1 do
                if (tcap[u,i]>0) and (dis[i]>dis[u]+cost[u,i]) then
                  begin
                    pre[i]:=u;
                    inc(tail);
                    dl[tail]:=i;
                    dis[i]:=dis[u]+cost[u,i];
                  end;
              inc(head);
            end;
    
          if dis[2*n+2*m+1]=maxlongint then  exit(false) else exit(true);
        end;
    
      begin
    
        read(n,m);
    
        for i:=1 to n do
          read(a[i]);
        for i:=1 to m do
          read(b[i]);
        for i:=1 to n do
          for j:=1 to m do
            read(c[i,j]);
    
        build;
    
        for i:=0 to 2*n+2*m+1 do
          for j:=0 to 2*n+2*m+1 do
              tcap[i,j]:=cap[i,j];
        while spfa1 do aug;
        writeln(ans);
    
    
      end.

    最大费用最大流

    uses math;
    
    var
     n,m,i,j :longint;
     ans:int64;
     dl:array[1..50000] of longint;
     cost,tcap,cap:array[0..501,0..501] of int64;
     dis:array[0..501] of longint;
     pre:array[0..501] of longint;
     a,b:array[1..250] of longint;
     c:Array[1..250,1..250] of longint;
    
     procedure build;
     var
      i,j:longint;
       begin
         for i:=1 to n do
           begin
             cap[0,i]:=maxlongint;
             cost[0,i]:=0;
           end;
    
         for i:=1 to n do
           begin
             cap[i,i+n]:=a[i];
             cost[i,i+n]:=0;
           end;
    
         for i:=1 to n do
           for j:=1 to m do
             begin
               cap[i+n,j+2*n]:=maxlongint;
               cost[i+n,j+2*n]:=c[i,j];
               cost[j+2*n,i+n]:=-c[i,j];
             end;
    
         for i:=1 to m do
           begin
             cap[i+2*n,i+2*n+m]:=b[i];
             cost[i+2*n,i+2*n+m]:=0;
           end;
    
         for i:=1 to m do
           begin
             cap[i+2*n+m,2*n+2*m+1]:=maxlongint;
             cost[i+2*n+m,2*n+2*m+1]:=0;
           end;
       end;
    
      procedure aug;
      var
       po:longint;
       mi:int64;
       pr:longint;
        begin
          po:=2*n+2*m+1;
          mi:=maxlongint;
          while po<>0 do
            begin
              pr:=pre[po];
              mi:=min(mi,tcap[pr,po]);
              po:=pr;
            end;
    
          po:=2*n+2*m+1;
          while po<>0 do
            begin
              pr:=pre[po];
              dec(tcap[pr,po],mi);
              inc(tcap[po,pr],mi);
              inc(ans,mi*cost[pr,po]);
              po:=pr;
            end;
        end;
    
    
    
      function spfa2:boolean;
      var
       i,u,head,tail:longint;
        begin
          for i:=1 to 2*m+2*n+1 do
             dis[i]:=-maxlongint;
          dis[0]:=0;
    
          head:=1;tail:=1;
          dl[1]:=0;
          while head<=tail do
            begin
              u:=dl[head];
              for i:=0 to 2*n+2*m+1 do
                if (tcap[u,i]>0) and (dis[i]<dis[u]+cost[u,i]) then
                  begin
                    pre[i]:=u;
                    inc(tail);
                    dl[tail]:=i;
                    dis[i]:=dis[u]+cost[u,i];
                  end;
              inc(head);
            end;
    
          if dis[2*n+2*m+1]=-maxlongint then  exit(false) else exit(true);
        end;
    
      begin
    
        read(n,m);
    
        for i:=1 to n do
          read(a[i]);
        for i:=1 to m do
          read(b[i]);
        for i:=1 to n do
          for j:=1 to m do
            read(c[i,j]);
    
        build;
    
        ans:=0;
        for i:=0 to 2*n+2*m+1 do
          for j:=0 to 2*n+2*m+1 do
              tcap[i,j]:=cap[i,j];
        while spfa2 do aug;
        writeln(ans);
    
      end.

    边表模板

    procedure addedge(u,v,cap,cost:longint);
       begin
         sid[tot].u:=u;
         sid[tot].v:=v;
         sid[tot].cap:=cap;
         sid[tot].cost:=cost;
         sid[tot].next:=nd[u];
         nd[u]:=tot;
         inc(tot);
         sid[tot].u:=v;
         sid[tot].v:=u;
         sid[tot].cap:=0;
         sid[tot].cost:=-cost;
         sid[tot].next:=nd[v];
         nd[v]:=tot;
         inc(tot);
       end;
    
      function spfa:boolean;
      var
       i,head,tail,u,p:longint;
        begin
    
          for i:=1 to n+1 do dis[i]:=maxlongint div 2;
          for i:=1 to n+1 do vis[i]:=true;
    
          head:=1;tail:=1;
          dl[1]:=0;
          while head<=tail do
            begin
              u:=dl[head];
              p:=nd[dl[head]];
              while p<>-1 do
                begin
                  if (sid[p].cap>0) and (dis[u]+sid[p].cost<dis[sid[p].v]) then
                    begin
                     if vis[sid[p].v]=true then
                      begin
                      inc(tail);
                      dl[tail]:=sid[p].v;
                      vis[sid[p].v]:=false;
                      end;
                      pre[sid[p].v]:=p;
                      dis[sid[p].v]:=dis[u]+sid[p].cost;
                    end;
                  p:=sid[p].next;
                end;
              vis[dl[head]]:=true;
              inc(head);
            end;
    
          if dis[n+1]=maxlongint div 2 then exit(false) else exit(true);
        end;
    
    
      procedure aug;
      var
       po,mi:longint;
        begin
          po:=n+1;
          mi:=maxlongint;
          while po<>0 do
            begin
              if sid[pre[po]].cap<mi then mi:=sid[pre[po]].cap;
              po:=sid[pre[po]].u;
            end;
    
          po:=n+1;
          while po<>0 do
            begin
              inc(ans,mi*sid[pre[po]].cost);
              dec(sid[pre[po]].cap,mi);
              inc(sid[pre[po] xor 1].cap,mi);
              po:=sid[pre[po]].u;
            end;
        end;

     -----------------------------------------------------------------------------------------

    BZOJ4276

    用线段树优化费用流

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
      struct edge{
          int fr,des,cap,cos,next;
      }sid[400001];
      
      struct treenode{
          int l,r,lc,rc;
      }tr[20001];
      
      int cnt,nd[40001],dl[4000001],head,tail,sor,tar,dis[40001],b[40001],path[40001],ans,scnt;
    
         void addedge(int fr,int to,int cap,int cos){
             sid[scnt].fr=fr;sid[scnt].des=to;sid[scnt].cap=cap;sid[scnt].cos=cos;sid[scnt].next=nd[fr];nd[fr]=scnt++;
             sid[scnt].fr=to;sid[scnt].des=fr;sid[scnt].cap=0;sid[scnt].cos=-cos;sid[scnt].next=nd[to];nd[to]=scnt++;
         }
         
        int spfa(){
            dl[head=tail=1]=sor;
            for (int i=1;i<=tar;i++) dis[i]=0,b[i]=0;
            b[sor]=1;
            dis[sor]=0;
            while (head<=tail){
                for (int p=nd[dl[head]];p!=-1;p=sid[p].next)
                    if ((sid[p].cap!=0)&&(dis[sid[p].des]<dis[dl[head]]+sid[p].cos)){
                        path[sid[p].des]=p;
                        if (b[sid[p].des]==0){
                            dl[++tail]=sid[p].des;
                            b[sid[p].des]=1;
                        }
                        dis[sid[p].des]=dis[dl[head]]+sid[p].cos;
                    }
                    b[dl[head++]]=0;        
            }
            
            if (dis[tar]==0) return(0);else return(1);
        }
        
        void aug(){
            int po=tar,flow=1e9;
    
            while (po!=sor){
                int p=path[po];
                flow=min(flow,sid[p].cap);
                po=sid[p].fr;
            }
                
            po=tar;
            
            while (po!=sor){
                int p=path[po];
                sid[p].cap-=flow;
                ans+=flow*sid[p].cos;
                sid[p^1].cap+=flow;
                po=sid[p].fr;
            }
        }
        
      void build(int l,int r){
          tr[++cnt].l=l;tr[cnt].r=r;
          if (l==r) {addedge(cnt,tar,1,0);return;}
          
          int t=cnt,mid=(l+r)>>1;
          tr[t].lc=cnt+1;addedge(t,cnt+1,1e9,0);
          build(l,mid);
          tr[t].rc=cnt+1;addedge(t,cnt+1,1e9,0);
          build(mid+1,r);
      }
     
      void query(int po,int l,int r,int fr){
          if (tr[po].l==l&&tr[po].r==r){
            addedge(fr,po,1e9,0);return;    
        }
        
        int mid=(tr[po].l+tr[po].r)>>1;
        if (l<=mid) query(tr[po].lc,l,min(mid,r),fr);
        if (r>mid)  query(tr[po].rc,max(mid+1,l),r,fr);
      }
    
      int main(){      
          int n,t1,t2,t3;
          scanf("%d",&n);
          sor=0;tar=30001;
          for (int i=sor;i<=tar;i++) nd[i]=-1;
          build(1,5000);
          
          for (int i=1;i<=n;i++){
            scanf("%d%d%d",&t1,&t2,&t3);t2--;
          addedge(sor,++cnt,1,t3);    
          query(1,t1,t2,cnt);
        }
        
        while (spfa()) 
          aug();
        
        printf("%d
    ",ans);
      }
  • 相关阅读:
    20145231第九周学习笔记
    20145231第八周学习笔记
    20145231《Java程序设计》第三次实验报告
    20145231第七周学习笔记
    20145231《Java程序设计》第二次实验报告
    测试「20200912测试总结」
    题解「Luogu4774 [NOI2018]屠龙勇士」
    总结「斯坦纳树」
    题解「AT1226 電圧」
    题解「AT1983 [AGC001E] BBQ Hard」
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/5237749.html
Copyright © 2020-2023  润新知