题目描述
GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 nn 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
输入输出格式
输入格式:
文件的第 11 行中有 11 个正整数 nn,表示有 nn 个仓库。
第 22 行中有 nn 个正整数,表示 nn 个仓库的库存量。
输出格式:
输出最少搬运量。
输入输出样例
输入样例#1: 复制
5
17 9 14 16 4
输出样例#1: 复制
11
[分析]
最小费用最大流
设超级源点为s,超级汇点为t
源点连接每个点,流为a[i],费用为0
每个点连接汇点,流为sum/n(平均数),费用为0
每个点连接他的前一个点和后一个点,可以流无限大,费用为1
然后模板就可以了
[代码]
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxm = 1050;
const int maxn = 1050;
const int INF = 0x3f3f3f3f;
int s, t, tot, n, m;
int a[maxn];
struct Edge {
int to, nxt, cap, flow, cost;
}edge[105000];
int Head[maxn], tol;
int pre[maxn], dis[maxn];
bool vis[maxn];
void addedge(int u, int v, int cap, int cost) {
edge[tol].to = v;
edge[tol].cap = cap;
edge[tol].cost = cost;
edge[tol].flow = 0;
edge[tol].nxt = Head[u];
Head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].cost = -cost;
edge[tol].flow = 0;
edge[tol].nxt = Head[v];
Head[v] = tol++;
}
bool spfa(int s, int t) {
queue<int> q;
for (int i = 0; i < tot; i++) {
dis[i] = INF; vis[i] = false; pre[i] = -1;
}
dis[s] = 0; vis[s] = true;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int i = Head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].to;
if (edge[i].cap > edge[i].flow&&dis[v] > dis[u] + edge[i].cost) {
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if (!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}
}
if (pre[t] == -1) return false;
return true;
}
int minCostMaxflow(int s, int t, int &cost) {
int flow = 0;
cost = 0;
while (spfa(s, t)) {
int Min = INF;
for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
if (Min > edge[i].cap - edge[i].flow)
Min = edge[i].cap - edge[i].flow;
for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
edge[i].flow += Min;
edge[i ^ 1].flow -= Min;
cost += edge[i].cost*Min;
}
flow += Min;
}
return flow;
}
int main() {
while (scanf("%d", &n) != EOF) {
int sum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
sum += a[i];
}
sum /= n;
s = n;
t = n + 1;
tot = n + 2;
memset(Head, -1, sizeof(Head));
tol = 0;
for (int i = 0; i < n; i++) {
addedge(s, i, a[i], 0);
addedge(i, t, sum, 0);
addedge(i, (i + 1) % n, INF, 1);
addedge(i, (i + n - 1) % n, INF, 1);
}
int cost;
int flow = minCostMaxflow(s, t, cost);
printf("%d\n", cost);
}
return 0;
}