[网络流24题 #17]运输问题

本来和job一样是一道水题,没有想到错误会出在循环的起始值上,这说明写代码时的智商还是有点低,应该多加训练,就是这样O__O"…

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define clean(x,y) memset(x,y,sizeof(x))
#define add(x) Q.push(x),v[x]=1
#define del(x) x=Q.front(),Q.pop(),v[x]=0
#define cmp(CurP,AnoP,CmpWay) (CmpWay? d[AnoP]<d[CurP]+a[i].cost:d[AnoP]>d[CurP]+a[i].cost)
#define MaxN 110
#define INF ~0U>>2
using namespace std;
const int lim[2]={INF,-(INF)}; 
int head[MaxN],p[MaxN][2],d[MaxN];
bool v[MaxN];
int n,m,tot,S,T;
struct edge
{
	int v,next,cap,cost;
	edge(int v1,int v2,int c,int b):v(v2),cap(c),cost(b),next(head[v1])
	{head[v1]=tot++;}
};
vector<edge> a;
inline void AddEdge(int x,int y,int cap,int cost)
{
	a.push_back(edge(x,y,cap,cost));
	a.push_back(edge(y,x,0,-cost));
}
inline void init()
{
	int w;
	clean(head,-1);
	cin>>m>>n;
	S=0,T=m+n+1;
	for(int i=1;i<=m;i++)
		scanf("%d",&w),
		AddEdge(S,i,w,0);
	for(int j=m+1;j<T;j++)
		scanf("%d",&w),
		AddEdge(j,T,w,0);
	for(int i=1;i<=m;i++)
		for(int j=m+1;j<T;j++)
			scanf("%d",&w),
			AddEdge(i,j,INF,w);
}
inline bool spfa(bool way)
{
	int i,x,y;
	queue<int> Q;
	clean(p,-1);
	clean(v,0);
	for(i=1;i<=T;i++) d[i]=lim[way];
	add(S),d[S]=0;
	while(!Q.empty())
	{
		del(x);
		for(i=head[x];i!=-1;i=a[i].next)
		{
			y=a[i].v;
			if(a[i].cap>0&&cmp(x,y,way))
			{
				d[y]=d[x]+a[i].cost;
				p[y][0]=i,p[y][1]=x;
				if(!v[y]) add(y);
			}
		}
	}
	return d[T]!=lim[way];
}
inline void RefreshNetwork()
{
	for(int i=0;i<tot;i+=2)
		a[i].cap+=a[i^1].cap,
		a[i^1].cap=0;
}
inline void work()
{
	int i,u,cost=0,flow;
	while(spfa(0))
	{
		flow=INF;
		for(i=p[T][0],u=p[T][1];i!=-1;i=p[u][0],u=p[u][1])
			if(flow>a[i].cap)
				flow=a[i].cap;
		for(i=p[T][0],u=p[T][1];i!=-1;i=p[u][0],u=p[u][1])
			a[i].cap-=flow,
			a[i^1].cap+=flow;
		cost+=flow*d[T];
	}
	cout<<cost<<endl;
	RefreshNetwork(),cost=0;
	while(spfa(1))
	{
		flow=INF;
		for(i=p[T][0],u=p[T][1];i!=-1;i=p[u][0],u=p[u][1])
			if(flow>a[i].cap)
				flow=a[i].cap;
		for(i=p[T][0],u=p[T][1];i!=-1;i=p[u][0],u=p[u][1])
			a[i].cap-=flow,
			a[i^1].cap+=flow;
		cost+=flow*d[T];
	}
	cout<<cost;
}
int main()
{
	init();
	work();
	return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值