zoukankan      html  css  js  c++  java
  • 最小费用最大流——小结1

    最小费用最大流

    模板题

    思路:在费用保持最小的情况下,找出最大流。

          1.我们每次找到一条从源点到汇点的最短路(spfa)

          2.然后找到最短路径上剩余流量最小的边,把整条路径上边的流量都减少那么多

          3.更新最小费用

          4.重复操作,直到S-T无路径

    采用了学长讲的优化:

        SLF优化:每次入队的时候把这个点的费用与队首的点的费用相比较

             如果比那个点的费用小,插到队首,否则插到队尾

                          

    代码

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    #define inf 0x3f3f3f3f
    #define MN 5005
    #define ME 100005
    int n,m,S,T;
    int q[ME*2+5],tp,tl,ans,from[MN+5],d[MN+5],hr[MN+5],cnt=1,res;
    bool inq[MN+5];
    struct edge{int fr,to,nex,w,c;}e[ME];
    inline void ins(int f,int t,int w,int c){
        e[++cnt]=(edge){f,t,hr[f],w,c};hr[f]=cnt;
        e[++cnt]=(edge){t,f,hr[t],0,-c};hr[t]=cnt;
    }
    inline bool spfa(){
        register int i;
        memset(d,0x3f,sizeof d);
        memset(inq,0,sizeof inq);
        q[tp=tl=MN]=S;inq[S]=1;d[S]=0;
        while(tp>=tl){
            int u=q[tl++];inq[u]=0;
            for(i=hr[u];i;i=e[i].nex)
            if(e[i].w>0&&d[u]+e[i].c<d[e[i].to]){
                d[e[i].to]=d[u]+e[i].c;from[e[i].to]=i;
                if(!inq[e[i].to]){
                    if(d[e[i].to]<d[q[tl]]) q[--tl]=e[i].to;
                    else q[++tp]=e[i].to; inq[e[i].to]=1;
                }
            }
        }
        return d[T]!=inf;
    }
    inline void mcf(){
        int minn=inf,i;
        for(i=from[T];i;i=from[e[i].fr])
            minn=min(minn,e[i].w);
        res+=minn;
        for(i=from[T];i;i=from[e[i].fr]){
            ans+=minn*e[i].c;
            e[i].w-=minn;e[i^1].w+=minn;
        }
    }
    int main(){
        register int u,v,w,c,i;
        n=read(),m=read();S=read(),T=read();
        for(i=1;i<=m;i++){
            u=read(),v=read(),w=read(),c=read();
            ins(u,v,w,c);
        }
        while(spfa()) mcf();
        printf("%d %d
    ",res,ans);
        return 0;
    }

    评测情况:

    补充:

      1.其实费用流同样可以多路增广。

      2.实践证明,spfa时,从T到S反过来操作会快很多

    代码

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    #define inf 0x3f3f3f3f
    #define ME 100005
    #define MN 5005
    int n,m,S,T,maxflow,mincost;
    struct edge{int to,w,c,nex;}e[ME];int hr[MN],cnt=1;
    
    inline void ins(int f,int t,int w,int c){
        e[++cnt]=(edge){t,w,c,hr[f]};hr[f]=cnt;
        e[++cnt]=(edge){f,0,-c,hr[t]};hr[t]=cnt; 
    }
    int d[MN],q[ME],l,r;
    bool inq[MN],vis[MN];
    
    bool spfa(){
        memset(d,0x3f,sizeof d);
        q[l=r=MN]=T;d[T]=0;inq[T]=1;
        while(l<=r){
            int u=q[l++];inq[u]=0;
            for(int i=hr[u];i;i=e[i].nex)
            if(e[i^1].w&&d[e[i].to]>d[u]-e[i].c){
                d[e[i].to]=d[u]-e[i].c;
                if(!inq[e[i].to])
                d[e[i].to]<d[q[l]]?q[--l]=e[i].to:q[++r]=e[i].to,inq[e[i].to]=1;
            }
        }
        return d[S]!=inf;
    }
    
    int flow(int x,int f){
        vis[x]=1;
        if(x==T) return f;
        int used=0,w;
        for(int i=hr[x];i;i=e[i].nex)
            if(!vis[e[i].to]&&d[x]-e[i].c==d[e[i].to]&&e[i].w){
                w=flow(e[i].to,min(f-used,e[i].w));
                used+=w;mincost+=w*e[i].c;
                e[i].w-=w,e[i^1].w+=w;
                if(f==used) return f;
            }
        return used;
    }
    
    inline void solve(){
        while(spfa()){
            do{
                memset(vis,0,sizeof vis);
                maxflow+=flow(S,inf);
            }while(vis[T]);
        }
    }
    
    int main(){
        int i,u,v,y,z;
        n=read(),m=read(),S=read(),T=read();
        for(i=1;i<=m;i++){
            u=read(),v=read(),y=read(),z=read();
            ins(u,v,y,z);
        }
        solve();
        printf("%d %d
    ",maxflow,mincost);
        return 0;
    }

    评测情况:


    来自PaperCloud的博客,未经允许,请勿转载,TKS!

  • 相关阅读:
    zookeeper使用场景
    zookeeper安装配置
    hadoop 远程调试
    deep learning笔记
    Sentiment Analysis(1)-Dependency Tree-based Sentiment Classification using CRFs with Hidden Variables
    PRML阅读笔记 introduction
    Python 学习笔记(2)
    python nltk 学习笔记(5) Learning to Classify Text
    python nltk 学习笔记(4) Writing Structured Programs
    python nltk 学习笔记(3) processing raw text
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/9121010.html
Copyright © 2011-2022 走看看