题目描述

G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。

输入格式

文件的第 1 行中有 1 个正整数 n,表示有 n 个仓库。

2 行中有 n 个正整数,表示 n 个仓库的库存量。

输出格式

输出最少搬运量。

输入输出样例

输入 #1
5
17 9 14 16 4
输出 #1
11

说明/提示

1≤n≤1001 \leq n \leq 1001n100

 

思路:建立超级源和超级汇,∵平衡时每个仓库的容量都是(Σa[i] )/ n,所以a[i] > avy的仓库,让它流向超级汇,以便过剩的流量能流出,a[i] < avy的仓库,让它连向超级源,使过剩的流量能流入。

     对每个仓库之间连一条容量+OO的,花费为1的边,跑最小费用最大流

 

 

 

 

 

 

 

#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <iostream> #include <vector>

using namespace std; typedef long long LL; const int maxn = 1e5 +7; const int inf  = 0x3f3f3f3f; int n, m, s, t; int head[maxn],pre[maxn],inq[maxn],dis[maxn]; int a[maxn]; int cnt = 1; struct edge { int u,to,nxt,w,c; }e[maxn << 1]; template<class T>inline void read(T &res) { char c;T flag=1; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; } inline void BuildGraph(int u, int v, int w, int cost) { e[++cnt] = (edge){u, v, head[u], w,  cost}, head[u] = cnt; e[++cnt] = (edge){v, u, head[v], 0, -cost}, head[v] = cnt;///反向边
} queue < int > q; bool SPFA(int x) { memset(inq, 0, sizeof(inq)); for(int i = s; i <= t; i++) { dis[i] = inf; } q.push(x); dis[x] = 0; inq[x] = 1; while(!q.empty()) { int u = q.front(); q.pop(); inq[u] = 0; for(int i = head[u]; i; i = e[i].nxt) { int v = e[i].to, w = e[i].c; if(e[i].w) { if(dis[u] + w < dis[v]) { dis[v] = dis[u] + w; pre[v] = i; if(!inq[v]) { q.push(v); inq[v] = 1; } } } } } if(dis[t] == inf) return 0; return 1; } int MCMF() { int ans = 0; while(SPFA(s)) { int temp = inf; for(int i = pre[t]; i; i = pre[e[i].u]) { temp = min(temp, e[i].w); } for(int i = pre[t]; i; i = pre[e[i].u]) { e[i].w -= temp; e[i^1].w += temp; ans += e[i].c * temp; //printf("ans:%d\n",ans);
 } } return ans; } int main() { read(n); int sum = 0; for(int i = 1; i <= n; i++) { read(a[i]); sum += a[i]; } sum /= n; s = 0; t = 2*n + 1; for(int i = 1; i <= n; i++) { if(sum > a[i]) { BuildGraph(s, i, sum - a[i], 0); } if(sum < a[i]) { BuildGraph(i, t, a[i] - sum, 0); } } for(int i = 1; i <= n; i++) { if(i == 1) { BuildGraph(i, n, inf, 1); BuildGraph(i, 2, inf, 1); } else if(i == n) { BuildGraph(n, 1, inf, 1); BuildGraph(n, n-1, inf, 1); } else { BuildGraph(i, i+1, inf, 1); BuildGraph(i, i-1, inf, 1); } } printf("%d\n",MCMF()); return 0; }