网络流24题(十九)
网络流24题(十九)
十九、负载平衡问题
题目描述
G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
输入格式
第一行一个正整数 n,表示有 n 个仓库。
第二行 n 个正整数,表示 n 个仓库的库存量。
输出格式
输出最少搬运量。
题解
模型
最小费用最大流
开始觉得需要建二分图,但二分图只会跑一次,要点与点之间要多次联系的的话就不需要二分图。
单次考虑二分图。
建图
把每一个仓库看作点,让它与旁边两个点连边费用为1,容量无限,源点s与每个点连边,容量为仓库库存量,费用为0,每个点与汇点t连边,容量为仓库库存平均值,费用为0。跑最小费用最大流即可。
代码
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
using namespace std;
#define ll long long
const ll inf = 0x3f3f3f3f;
const int N = 5000,M = 5e4+50;
ll head[N],cnt = 1;
struct Edge{
ll to,w,cost,nxt;
}edge[M*2];
void add(ll u,ll v,ll w,ll c){
edge[++cnt] = {v,w,c,head[u]};
head[u] = cnt;
}
void add2(ll u,ll v,ll w,ll cost){
add(u,v,w,cost);
add(v,u,0,-cost);
}
ll s,t,dis[N],cur[N];
bool inq[N],vis[N];
queue<ll>Q;
bool spfa(){
while(!Q.empty()) Q.pop();
copy(head,head+N,cur);
fill(dis,dis+N,inf);
dis[s] = 0;
Q.push(s);
while(!Q.empty()){
ll p = Q.front();
Q.pop();
inq[p] = false;
for(ll e = head[p];e;e = edge[e].nxt){
ll to = edge[e].to,vol = edge[e].w;
if(vol > 0 && dis[to]>dis[p]+edge[e].cost){
dis[to] = dis[p] + edge[e].cost;
if(!inq[to]){
Q.push(to);
inq[to] = true;
}
}
}
}
return dis[t] != inf;
}
ll dfs(ll p = s,ll flow = inf){
if(p == t) return flow;
vis[p] = true;
ll rmn = flow;
for(ll eg = cur[p];eg && rmn;eg = edge[eg].nxt){
cur[p] = eg;
ll to = edge[eg].to,vol = edge[eg].w;
if(vol > 0 && !vis[to]&&dis[to] == dis[p]+edge[eg].cost){
ll c = dfs(to,min(vol,rmn));
rmn -= c;
edge[eg].w -= c;
edge[eg^1].w += c;
}
}
vis[p] = false;
return flow-rmn;
}
ll maxflow,mincost;
void dinic(){
maxflow = 0,mincost = 0;
while(spfa()){
ll flow = dfs();
maxflow += flow;
mincost += dis[t]*flow;
}
}
ll n,a[N];
int main(){
//ios::sync_with_stdio(false);
cin>>n;
ll sum = 0;
for(ll i = 0;i < n;i++)cin>>a[i],sum+=a[i];
//cout<<sum<<endl;
for(ll i = 0;i < n;i++){
ll l = (i-1+n)%n,r = (i+1)%n;
// cout<<i<<' '<<l<<' '<<r<<endl;
add2(i,l,inf,1);
add2(i,r,inf,1);
}
s = n,t = n+1;
for(ll i = 0;i < n;i++){
add2(s,i,a[i],0);
add2(i,t,sum/n,0);
}
dinic();
cout<<mincost<<endl;
return 0;
}