1 条题解

  • 0
    @ 2025-8-24 21:55:35

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 徐致远
    **

    搬运于2025-08-24 21:55:35,当前版本为作者最后更新于2019-03-18 12:38:12,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    好经典的模型。

    题解

    乍一看就是一个二分图。

    但是要求很明显要求最小费用最大流。

    考虑如何建模。

    由于每一个仓库只能流出定量的货物,但是又不能把每一个仓库看做源。

    所以把所有货物都连到同一个源上,连到第ii个仓库的边嘚的容量为AiA_i,费用为00

    每一家零售店又都连到一个汇上,从第ii家零售店连出的边的容量为BiB_i,费用为00

    中间从仓库到零售店的边就按照题目里的说的那样连,容量为++\infty

    1.png

    然后直接跑最小费用最大流就好了。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=210,maxm=20205,inf=0x3F3F3F3F;
    int m,n,S,T,tot,lnk[maxn],son[maxm],nxt[maxm],w[maxm],cap[maxm],que[maxn],lst[maxn],pre[maxn],dist[maxn],flow[maxn],ans;bool vis[maxn];
    inline int read()
    {
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
    	return ret*f;
    }
    inline void add_e(int x,int y,int z,int c){tot++;son[tot]=y;w[tot]=z;cap[tot]=c;nxt[tot]=lnk[x];lnk[x]=tot;}
    inline void MinCostMaxFlow(int flg)
    {
    	while(true)
    	{
    		if(flg==1) memset(dist,63,sizeof(dist));
    		else memset(dist,192,sizeof(dist));
    		memset(flow,63,sizeof(flow));
    		int hed=0,til=1;
    		que[1]=S;dist[S]=0;vis[S]=true;pre[T]=0;
    		while(hed!=til)
    		{
    			hed=(hed+1)%maxn;vis[que[hed]]=false;
    			for(int i=lnk[que[hed]];i;i=nxt[i])
    			{
    				if(cap[i]&&((flg==1&&dist[que[hed]]+w[i]<dist[son[i]])||(flg==-1&&dist[que[hed]]+w[i]>dist[son[i]])))
    				{
    					dist[son[i]]=dist[que[hed]]+w[i];
    					pre[son[i]]=que[hed];
    					lst[son[i]]=i;
    					flow[son[i]]=min(flow[que[hed]],cap[i]);
    					if(!vis[son[i]])
    					{
    						vis[son[i]]=true;
    						til=(til+1)%maxn;
    						que[til]=son[i];
    					}
    				}
    			}
    		}
    		if(pre[T]==0) return;
    		ans+=flow[T]*dist[T];
    		int p=T;
    		while(p!=S)
    		{
    			cap[lst[p]]-=flow[T];
    			cap[(lst[p]&1)?lst[p]+1:lst[p]-1]+=flow[T];
    			p=pre[p];
    		}
    	}
    }
    int main()
    {
    	m=read();n=read();S=1;T=m+n+2;
    	for(int i=1;i<=m;i++)
    	{
    		int ai=read();
    		add_e(S,i+1,0,ai);
    		add_e(i+1,S,0,0);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		int bi=read();
    		add_e(i+m+1,T,0,bi);
    		add_e(T,i+m+1,0,0);
    	}
    	for(int i=1;i<=m;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			int cij=read();
    			add_e(i+1,j+m+1,cij,inf);
    			add_e(j+m+1,i+1,-cij,0);
    		}
    	}
    	MinCostMaxFlow(1);
    	printf("%d\n",ans);
    	for(int i=2;i<=tot;i+=2){cap[i-1]+=cap[i];cap[i]=0;}
    	ans=0;
    	MinCostMaxFlow(-1);
    	printf("%d\n",ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    2969
    时间
    1000ms
    内存
    250MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者