[洛谷P4015]运输问题

题目大意:有m个仓库和n个商店。第i个仓库有 $a_{i}$ 货物,第j个商店需要$b_{j}$个货物。从第i个仓库运送每单位货物到第j个商店的费用为$c_{i,j}$​​。求出最小费用和最大费用

题解:费用流,最大费用的时候把价钱和答案都取反

卡点:1.数组开小

C++ Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#define maxn 250
using namespace std;
const int inf=0x3f3f3f3f;
int n,m;
int mp[maxn][maxn],a[maxn],b[maxn];
int d[maxn],pre[maxn];
int q[maxn],h,t;
int st=1,ed;
int head[maxn],cnt=2;
bool vis[maxn];
struct Edge{
    int to,nxt,w,cost;
}e[maxn*maxn<<1];
char ch;
void read(int &x){
    ch=getchar();
    while (!isdigit(ch))ch=getchar();
    for (x=ch^48,ch=getchar();isdigit(ch);ch=getchar())x=x*10+(ch^48);
}
inline int min(int a,int b){return a<b?a:b;}
void add(int a,int b,int c,int d){
    e[cnt]=(Edge){b,head[a],c,d};head[a]=cnt;
    e[cnt^1]=(Edge){a,head[b],0,-d};head[b]=cnt^1;
    cnt+=2;
}
void build(int op=1){
    for (int i=1;i<=m;i++)add(st,i+1,a[i],0);
    for (int i=1;i<=n;i++)add(m+i+1,ed,b[i],0);
    for (int i=1;i<=m;i++){
        for (int j=1;j<=n;j++)add(i+1,m+j+1,inf,mp[i][j]*op);
    }
}
bool spfa(){
    int x;
    memset(d,0x3f,sizeof d);
    d[q[h=t=1]=st]=0;
    while (h<=t){
        vis[x=q[h++]]=false;
        for (int i=head[x];i;i=e[i].nxt){
            int to=e[i].to;
            if (e[i].w&&d[to]>d[x]+e[i].cost){
                d[to]=d[x]+e[i].cost;
                pre[to]=i;
                if (!vis[to])vis[q[++t]=to]=true;
            }
        }
    }
    return d[ed]!=inf;
}
int update(){
    int ans,mf=inf;
    for (int i=pre[ed];i;i=pre[e[i^1].to])mf=min(mf,e[i].w);
    ans=mf*d[ed];
    for (int i=pre[ed];i;i=pre[e[i^1].to])e[i].w-=mf,e[i^1].w+=mf;
    return ans;
}
void MCMF(int op=1){
    int ans=0;
    while (1){
	    int x;
	    memset(d,0x3f,sizeof d);
	    d[q[h=t=1]=st]=0;
	    while (h<=t){
	        vis[x=q[h++]]=false;
	        for (int i=head[x];i;i=e[i].nxt){
	            int to=e[i].to;
	            if (e[i].w&&d[to]>d[x]+e[i].cost){
	                d[to]=d[x]+e[i].cost;
	                pre[to]=i;
	                if (!vis[to])vis[q[++t]=to]=true;
	            }
	        }
	    }
	    if (d[ed]!=inf){
		    int mf=inf;
		    for (int i=pre[ed];i;i=pre[e[i^1].to])mf=min(mf,e[i].w);
		    ans+=mf*d[ed];
		    for (int i=pre[ed];i;i=pre[e[i^1].to])e[i].w-=mf,e[i^1].w+=mf;
		}else break;
	}
    printf("%d
",ans*op);
}
int main(){
    read(m),read(n);
    for (int i=1;i<=m;i++)read(a[i]);
    for (int i=1;i<=n;i++)read(b[i]);
    for (int i=1;i<=m;i++){
        for (int j=1;j<=n;j++)read(mp[i][j]);
    }
    ed=n+m+2; 
    build();
    MCMF();
    memset(head,0,sizeof head);cnt=2;
    build(-1);
    MCMF(-1);
    return 0;
} 

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/9130341.html