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;
    }
  • 相关阅读:
    高可用性GRE+IPSEC中心—分支
    高可用性GRE+IPSEC中心—分支
    高可用性GRE+IPSEC中心—分支
    mysql数据库移植
    mysql数据库移植
    mysql数据库移植
    mysql数据库移植
    Linux 查看进程资源--ps、top命令
    比特币底层设计剖析
    比特币的P2P网络协议
  • 原文地址:https://www.cnblogs.com/zsq259/p/10513223.html
Copyright © 2011-2022 走看看