zoukankan      html  css  js  c++  java
  • 题解 【网络流24题】运输问题

    题面

    解析

    这也就是一道费用流的模板题啊!

    将S与仓库连边,流量为存货,费用为0,

    商店与T连边,流量为需求,费用为0,

    (S,T反过来也可以)。

    然后把每个仓库与商店连边,

    流量为INF,费用为c[i][j],

    再spfa+EK求最小费用最大流,最大费用最大流即可(应该不需要证明吧)。

    上AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return f*sum;
    }
    
    const int INF=0x3f3f3f3f;
    struct node{
        int next,to,w,v;
    }e[100001];
    int n,m,s,t;
    int head[100001],cnt=1;
    int a[10001],b[10001],c[1001][1001];
    int pre[100001],d[100001],inq[100001],id[100001];
    
    void add(int x,int y,int v,int w){
        e[++cnt].to=head[x];
        e[cnt].next=y;
        e[cnt].v=v;
        e[cnt].w=w;
        head[x]=cnt;
    }
    
    bool minspfa(){
        memset(d,0x3f,sizeof(d));
        memset(pre,0,sizeof(pre));
        memset(inq,0,sizeof(inq));
        int que[100001]={0};
        int h=1,tail=1;
        que[1]=s;
        d[s]=0;
        while(h<=tail){
            int x=que[h];
            inq[x]=0;
            h++;
            for(int i=head[x];i;i=e[i].to){
                int k=e[i].next;
                if(e[i].v&&d[k]>d[x]+e[i].w){
    
                    pre[k]=x;
                    id[k]=i;
                    d[k]=d[x]+e[i].w;
                    if(!inq[k]) que[++tail]=k;
                    inq[k]=1;
                }
            }
        }
        return d[t]!=INF;
    }
    
    bool maxspfa(){
        memset(d,-0x3f,sizeof(d));
        memset(pre,0,sizeof(pre));
        memset(inq,0,sizeof(inq));
        int que[100001]={0};
        int h=1,tail=1;
        que[1]=s;
        d[s]=0;
        while(h<=tail){
            int x=que[h];
            inq[x]=0;
            h++;
            for(int i=head[x];i;i=e[i].to){
                int k=e[i].next;
                if(e[i].v&&d[k]<d[x]+e[i].w){
    
                    pre[k]=x;
                    id[k]=i;
                    d[k]=d[x]+e[i].w;
                    if(!inq[k]) que[++tail]=k;
                    inq[k]=1;
                }
            }
        }
        return d[t]>-1044266559;
    }
    
    
    void EK1(){
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++){
            add(s,i,a[i],0);
            add(i,s,0,0);
            for(int j=1;j<=n;j++){
                add(i,j+m,INF,c[i][j]);
                add(j+m,i,0,-c[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            add(i+m,t,b[i],0);
            add(t,i+m,0,0);
        }
        int cost=0;
        while(minspfa()){      
            int mi=INF;
            for(int i=t;i!=s;i=pre[i]){
                mi=min(mi,e[id[i]].v);
            }
            for(int i=t;i!=s;i=pre[i]){
                e[id[i]].v-=mi;
                e[id[i]^1].v+=mi;
            }
            cost+=mi*d[t];
        }
        printf("%d
    ",cost);
    }
    
    void EK2(){
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++){
            add(s,i,a[i],0);
            add(i,s,0,0);
            for(int j=1;j<=n;j++){
                add(i,j+m,INF,c[i][j]);
                add(j+m,i,0,-c[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            add(i+m,t,b[i],0);
            add(t,i+m,0,0);
        }
        int cost=0;
        while(maxspfa()){      
            int mi=INF;
            for(int i=t;i!=s;i=pre[i]){
                mi=min(mi,e[id[i]].v);
            }
            for(int i=t;i!=s;i=pre[i]){
                e[id[i]].v-=mi;
                e[id[i]^1].v+=mi;
            }
            cost+=mi*d[t];
        }
        printf("%d
    ",cost);
        
    }
    
    int main(){
        m=read();n=read();
        s=m+n+1;t=m+n+2;
        for(int i=1;i<=m;i++){
            a[i]=read();
        }
        for(int i=1;i<=n;i++){
            b[i]=read();
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                c[i][j]=read();
            }
        }
        EK1();
        EK2();
        return 0;
    }
  • 相关阅读:
    Advanced Configuration Tricks
    Reviewing the Blog Module
    Editing and Deleting Data
    Making Use of Forms and Fieldsets
    Understanding the Router
    SQL Abstraction and Object Hydration
    Preparing for Different Databases
    Java学习理解路线图
    Openstack学习历程_1_视频
    CentOS安装Nginx负载
  • 原文地址:https://www.cnblogs.com/zsq259/p/10513223.html
Copyright © 2011-2022 走看看