网络流24题之运输问题
Posted hbxblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流24题之运输问题相关的知识,希望对你有一定的参考价值。
题目链接:传送门
网络流最关键的肯定是建图对吧,那么怎么建呢,观察题目,假设两个超级点S,t,将s和所有仓库相连,流为ai,将t与所有商店相连,流为bj;
现在一个图已经建好了,问题是求什么?求的是最小运输费用和对大运输费用,所以这道题是一个最小(大)费用最大流,所以s和所有仓库相连,流为ai,费用为0,将t与所有商店相连,流为bj,费用为0,再将仓库和商店相连,流为inf((极大值)费用为c[i][j].
这样以后会发现这个图很标准,最小费用最大流很容易跑,但是最大费用最小流怎么跑?
可以将问题转换一下,应为最大费用的相反数是所有费用中最小的,所以可以将所有的费用去相反数,最后求出最小费用最大流的结果取相反数就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9')
x=x*10+c-'0',c=getchar();
return x*f;
}
struct node{
int to,next,v,w;
}a[100001];
int dis[1001],f[1001],pre[1001],fa[1001],head[1001],cnt,n,m,s,t,z,w,ans,ans1;
void add(int x,int y,int c,int v){
a[++cnt].to=y;
a[cnt].next=head[x];
a[cnt].v=c;
a[cnt].w=v;
head[x]=cnt;
}
queue<int> q ;
int spfa() {
memset(dis,127,sizeof(dis));
memset(f,0,sizeof(f));
q.push(s);
f[s]=1;
int inf=dis[1];
dis[s]=0;
while(!q.empty()) {
int now=q.front();
q.pop();
f[now]=0;
for(int i=head[now]; i; i=a[i].next) {
int v=a[i].to;
if(dis[v]>dis[now]+a[i].w&&a[i].v) {
dis[v]=dis[now]+a[i].w;
fa[v]=now;
pre[v]=i;
if(!f[v])
q.push(v),f[v]=1;
}
}
}
if(dis[t]!=inf)
return 1;
return 0;
}
void answer() {
ans=0,ans1=0;
while(spfa()) {
int minx=2147483647;
for(int i=t; i!=s; i=fa[i])
minx=min(minx,a[pre[i]].v);
ans+=minx,ans1+=dis[t]*minx;
for(int i=t; i!=s; i=fa[i]) {
a[pre[i]].v-=minx;
if(pre[i]%2)
a[pre[i]+1].v+=minx;
else
a[pre[i]-1].v+=minx;
}
}
}
int x[1001][1001],xx,y[1001];
int main(){
n=read(),m=read();
t=n+m+1;
for(int i=1;i<=n;i++)
xx=read(),add(s,i,xx,0),add(i,s,0,0),y[i]=xx;
for(int i=1;i<=m;i++)
xx=read(),add(i+n,t,xx,0),add(t,i+n,0,0),y[i+n]=xx;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
x[i][j]=read(),add(i,j+n,10000000,x[i][j]),add(j+n,i,0,-x[i][j]);
answer();
printf("%d
",ans1);
memset(head,0,sizeof(head)),cnt=0;
for(int i=1;i<=n;i++)
add(s,i,y[i],0),add(i,s,0,0);
for(int i=1;i<=m;i++)
add(i+n,t,y[i+n],0),add(t,i+n,0,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
add(i,j+n,10000000,-x[i][j]),add(j+n,i,0,x[i][j]);
answer();
printf("%d",-ans1);
}
以上是关于网络流24题之运输问题的主要内容,如果未能解决你的问题,请参考以下文章