codevs1914 运输问题


题目描述 Description

W 公司有m个仓库和n 个零售商店。第i 个仓库有ai 个单位的货物;第j 个零售商店
需要bj个单位的货物。货物供需平衡,即  sum(si)=sum(bj)
。从第i 个仓库运送每单位货物到
第j 个零售商店的费用为cij 。试设计一个将仓库中所有货物运送到零售商店的运输方案,
使总运输费用最少。
编程任务:
对于给定的m 个仓库和n 个零售商店间运送货物的费用,计算最优运输方案和最差运输方案。

输入描述 Input Description

的第1行有2 个正整数m和n,分别表示仓库数和
零售商店数。接下来的一行中有m个正整数ai ,1≤i≤m,表示第i个仓库有ai 个单位的货
物。再接下来的一行中有n个正整数bj ,1≤j≤n,表示第j个零售商店需要bj 个单位的货
物。接下来的m行,每行有n个整数,表示从第i 个仓库运送每单位货物到第j个零售商店
的费用cij 。

输出描述 Output Description

将计算出的最少运输费用和最多运输费用输出

样例输入 Sample Input

2 3
220 280
170 120 210
77 39 105
150 186 122

样例输出 Sample Output

48500
69140


啊啊啊啊啊啊啊啊
又是上次的错误
调了一个多小时
感谢某位大佬(哭唧唧。。。)
题目本身其实并不难
只是要记得跑最短路时dis数组初始化为inf
最长路dis数组初始化为-inf!dis数组初始化为-inf!dis数组初始化为-inf!
当没有负权边时可为-1,但是因为费用流反向弧费用为原流的相反数
所以原来为正数的边权变为了负数
所以 dis数组初始化为-inf!
每次都是因为仅初始为-1而调很久
所以保险起见都初始为-inf吧
代码写得略丑
见谅见谅
#include<cstdio>
#include<cstring>
#include<iostream>
const int inf=0x3f3f3f3f,N=50000;
struct node
{
	int to,next,v,c,from;
}e[1000000],f[1000000];
int first[N],dis[N],qu[N],bo[N],from[N],first2[N];
int cnt=1,s,t,ans=0;
void insert(int u,int v,int q,int c)
{
	e[++cnt].to=v;e[cnt].from=u;e[cnt].next=first[u];first[u]=cnt;e[cnt].v=q;e[cnt].c=c;
	e[++cnt].to=u;e[cnt].from=v;e[cnt].next=first[v];first[v]=cnt;e[cnt].v=0;e[cnt].c=-c;
	cnt-=2;
	f[++cnt].to=v;f[cnt].from=u;f[cnt].next=first2[u];first2[u]=cnt;f[cnt].v=q;f[cnt].c=c;
	f[++cnt].to=u;f[cnt].from=v;f[cnt].next=first2[v];first2[v]=cnt;f[cnt].v=0;f[cnt].c=-c;
}
bool spfa()
{
	memset(dis,inf,4*(t+5));
	int i=1,j=2;
	qu[1]=s;bo[s]=1;dis[s]=0;
	while(i!=j)
	{
		int r=qu[i++];bo[r]=0;if(i==N)	i=0;
		for(int k=first[r];k;k=e[k].next)
		{
			if(e[k].v>0&&dis[e[k].to]>dis[r]+e[k].c)
			{
				dis[e[k].to]=dis[r]+e[k].c;
				from[e[k].to]=k;
				if(!bo[e[k].to])
				{
					if(dis[e[k].to]<dis[i])	
					{
						i--;if(i<0)	i=N-1;
						qu[i]=e[k].to;
					}
					else qu[j++]=e[k].to;if(j==N)j=0;
					bo[e[k].to]=1;
				}
			}	
		}
	}
	if(dis[t]==inf)	return 0;
	return 1;
}
bool spfa2()
{
	for(int i=0;i<=t;i++)	dis[i]=-inf;
	int i=1,j=2;
	qu[1]=s;bo[s]=1;dis[s]=0;
	while(i!=j)
	{
		int r=qu[i++];bo[r]=0;if(i==N)	i=0;
		for(int k=first2[r];k;k=f[k].next)
		{
			if(f[k].v>0&&dis[f[k].to]<dis[r]+f[k].c)
			{
				dis[f[k].to]=dis[r]+f[k].c;
				from[f[k].to]=k;
				if(!bo[f[k].to])
				{
					if(dis[f[k].to]>dis[i])	
					{
						i--;if(i<0)	i=N-1;
						qu[i]=f[k].to;
					}
					else qu[j++]=f[k].to;if(j==N)j=0;
					bo[f[k].to]=1;
				}
			}	
		}
	}
	if(dis[t]==-inf)	return 0;
	return 1;
}
void fa()
{
	int min=inf;
	for(int k=from[t];k;k=from[e[k].from])
	min=min<e[k].v?min:e[k].v;
	for(int k=from[t];k;k=from[e[k].from])
	ans+=min*e[k].c,e[k].v-=min,e[k^1].v+=min;
}
void fa2()
{
	int min=inf;
	for(int k=from[t];k;k=from[f[k].from])
		min=min<f[k].v?min:f[k].v;
	for(int k=from[t];k;k=from[f[k].from])
		ans+=min*f[k].c,f[k].v-=min,f[k^1].v+=min;
}
int main()
{
	int m,n,p;
	scanf("%d %d",&m,&n);
	s=0,t=n+m+1;
	for(int i=1;i<=m;i++)
	scanf("%d",&p),insert(s,i,p,0);	
	for(int i=1;i<=n;i++)
	scanf("%d",&p),insert(m+i,t,p,0);
	for(int i=1;i<=m;i++)
	for(int j=1;j<=n;j++)
	scanf("%d",&p),insert(i,m+j,inf,p);
	while(spfa())	fa();
	printf("%d\n",ans);
	ans=0;	
	while(spfa2())	fa2();
	printf("%d\n",ans);
	return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值