原点向多出的点减边 , 费用为0 , 流量为多出个数
少个数的点向汇点建边 , 费用为0 , 流量为少的个数
相邻两个建边 , 费用为1 , 流量为inf , 然后跑最小费用最大流
#include<bits/stdc++.h>
#define N 105
#define M 10050
#define inf 0x3fffffff
using namespace std;
int first[N],next[M],to[M],w[M],c[M],tot=1;
int n,a[N],s,st,ed,dis[N],vis[N],from[N],froms[N];
void add(int x,int y,int z,int v){
// cout<<x<<" "<<y<<" "<<z<<" "<<v<<endl;
next[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z,c[tot]=v;
next[++tot]=first[y],first[y]=tot,to[tot]=x,w[tot]=0,c[tot]=-v;
}
bool spfa(){
queue<int> q; q.push(st);
memset(dis,127,sizeof(dis)); dis[st] = 0; int Inf = dis[1];
memset(vis,0,sizeof(vis)); vis[st] = 1;
while(!q.empty()){
int x = q.front(); q.pop(); vis[x] = 0;
for(int i=first[x];i;i=next[i]){
int t=to[i]; if(w[i] && dis[t]>dis[x]+c[i]){
from[t] = x , froms[t] = i;
dis[t] = dis[x] + c[i];
if(!vis[t]) q.push(t), vis[t] = 1;
}
}
} return (dis[ed]!=Inf);
}
int calc(){
int u = ed , flow = inf;
while(u!=st){
flow = min(flow , w[froms[u]]);
u = from[u];
} u = ed;
while(u!=st){
w[froms[u]] -= flow;
w[froms[u] ^ 1] += flow;
u = from[u];
} return flow;
}
int dinic(){int ans=0; while(spfa()) ans += calc() * dis[ed]; return ans;}
int main(){
scanf("%d",&n); st=0,ed=n+1;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),s+=a[i];
s/=n; for(int i=1;i<=n;i++){
if(a[i]>s) add(st,i,a[i]-s,0);
if(a[i]<s) add(i,ed,s-a[i],0);
} for(int i=2;i<=n-1;i++){
add(i,i-1,inf,1); add(i,i+1,inf,1);
} add(1,2,inf,1),add(1,n,inf,1); add(n,n-1,inf,1); add(n,1,inf,1);
printf("%d",dinic()); return 0;
}