从原点到每一个仓库连线,流为仓库的值,费用0
从每一个仓库到汇点连线,流为平均值,费用0
相邻的仓库连线,流无限,费用1
跑出费用输出就好了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define N 105
using namespace std;
int n,tot,cnt,ans,a[N],to[12*N],rest[12*N],cost[12*N],ne[12*N],st[N];
int dis[N],f[N],queue[N],last[N],road[N],head,tail;
bool used[N];
void add(int k,int l,int o,int p){
to[++cnt]=l;
rest[cnt]=o;
cost[cnt]=p;
ne[cnt]=st[k];
st[k]=cnt;
}
bool SPFA(){
rep(i,0,n+1) dis[i]=10000000,used[i]=0,f[i]=0;
dis[0]=0;f[0]=10000000;used[0]=1;queue[1]=0;
head=0;tail=1;
while (head!=tail){
head=(head+1)%(n+2);
int x=queue[head];
used[x]=0;
for (int i=st[x];i!=0;i=ne[i]) if (rest[i]>0){
if (dis[x]+cost[i]<dis[to[i]]){
dis[to[i]]=dis[x]+cost[i];
f[to[i]]=min(rest[i],f[x]);
last[to[i]]=x;
road[to[i]]=i;
if (used[to[i]]==0){
tail=(tail+1)%(n+2);
queue[tail]=to[i];
used[to[i]]=1;
}
}
}
}
return f[n+1]>0;
}
void rset(int k){
if (k==0) return;
int l=last[k];
rset(l);
int i=road[k],o=f[n+1];
rest[i]-=o;
rest[i^1]+=o;
}
int main(){
scanf("%d",&n);
rep(i,1,n) scanf("%d",&a[i]),tot+=a[i];
tot/=n;cnt=1;
rep(i,1,n){
add(0,i,a[i],0);add(i,0,0,0);
add(i,n+1,tot,0);add(n+1,i,0,0);
add(i,i%n+1,10000000,1);add(i%n+1,i,0,-1);
add(i%n+1,i,10000000,1);add(i,i%n+1,0,-1);
}
while (SPFA()){
ans+=dis[n+1]*f[n+1];
rset(n+1);
}
printf("%d\n",ans);
system("pause");
}