网络流24题之负载平衡问题
题目描述
G 公司有 n个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
输入输出格式
输入格式:
文件的第 1 行中有 1 个正整数 n,表示有 n 个仓库。
第 2 行中有 n 个正整数,表示 n个仓库的库存量。
输出格式:
输出最少搬运量。
样例输入:
5
17 9 14 16 4
样例输出:
11
模拟赛贪心水过,第一道费用流。
所有仓库的数量都相等,就应该讲多余平均值的仓库运往少于平均值的仓库,多的仓库应该贡献,连向源点;少的仓库应该得到,连向汇点,且费用为0(因为费用指在两个相邻仓库中的运输单价)。
下一步,每两个相邻的公司也需要连一条+无穷的边权,费用为1.
之后就没什么了。
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
#define N 50000
int f[N],cost[N];
int val[N],to[N],head[N],nex[N];
int a[N];
int n;
int idx=1;
int S,T;
int sum;
int ans,maxflow;
int nowflow[N];
int inq[N];
int pre[N];
void addedge(int a,int b,int c,int d)
{
nex[++idx]=head[a];
head[a]=idx;
to[idx]=b;
val[idx]=c;
cost[idx]=d;
}
bool spfa(int S,int T)
{
memset(f,0x3f,sizeof(f));
memset(nowflow,0x3f,sizeof(nowflow));
memset(inq,0,sizeof(inq));
queue <int > q;
f[S]=0;
inq[S]=1;
q.push(S);
while(!q.empty())
{
int x=q.front();
q.pop();
inq[x]=0;
for(int i=head[x];i;i=nex[i])
{
if(val[i]&&f[to[i]]>f[x]+cost[i])
{
f[to[i]]=f[x]+cost[i];
nowflow[to[i]]=min(nowflow[x],val[i]);
pre[to[i]]=i;
if(!inq[to[i]])
{
inq[to[i]]=1;
q.push(to[i]);
}
}
}
}
if(f[T]>=0x3f3f3f3f)
return 0;
return 1;
}
void EK()
{
int x=T;
while(x!=S)
{
int i=pre[x];
val[i]-=nowflow[T];
val[i^1]+=nowflow[T];
x=to[i^1];
}
maxflow+=nowflow[T];
ans+=f[T]*nowflow[T];
}
int main()
{
scanf("%d",&n);
S=0,T=n+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sum/=n;
for(int i=1;i<=n;i++)
{
if(sum>a[i])
{
addedge(S,i,sum-a[i],0);
addedge(i,S,0,0);
}
else
{
addedge(i,T,a[i]-sum,0);
addedge(T,i,0,0);
}
}
for(int i=2;i<=n;i++)
{
addedge(i-1,i,1<<30,1);
addedge(i,i-1,0,-1);
addedge(i,i-1,1<<30,1);
addedge(i-1,i,0,-1);
}
addedge(n,1,1<<30,1);
addedge(1,n,0,-1);
addedge(1,n,1<<30,1);
addedge(n,1,0,-1);
while(spfa(S,T))
EK();
printf("%d",ans);
}

浙公网安备 33010602011771号