P4016 负载平衡问题
题目描述:
G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 n 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
思路:把大于平均值的节点和源点连边,容量为差值,费用为0,把小于平均值的节点和汇点连边,容量也为差值,费用为0,
再把相邻点连边,容量为inf,费用为1,跑最小费用最大流即可,别问为什么,问就是猜的.
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 600005; const int inf = 0x3f3f3f3f; struct edge { int f, t, nxt; ll flow, w; }e[maxn * 2]; int hd[maxn], tot = 1; void add(int f, int t, ll flow, ll w) { e[++tot] = { f,t,hd[f],flow ,w }; hd[f] = tot; e[++tot] = { t,f,hd[t],0,-w }; hd[t] = tot; } int s, t; int dis[maxn], pre[maxn]; ll maxflow, mincost; ll cyf[maxn]; bool inque[maxn]; int n; bool spfa() { memset(dis, 0x3f, sizeof(dis)); memset(inque, 0, sizeof(inque)); dis[s] = 0, inque[s] = 1, cyf[s] = inf; queue<int>q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); inque[u] = 0; for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (e[i].flow > 0 && dis[u] + e[i].w < dis[v]) { pre[v] = i; cyf[v] = min(cyf[u], e[i].flow); dis[v] = dis[u] + e[i].w; if (!inque[v]) { inque[v] = 1; q.push(v); } } } } return dis[t] != inf; } void mcmf() { maxflow = mincost = 0; while (spfa()) { int x = t; maxflow += cyf[t]; mincost += dis[t] * cyf[t]; while (x != s) { int i = pre[x]; e[i].flow -= cyf[t]; e[i ^ 1].flow += cyf[t]; x = e[i].f; } } } int a[105]; int main() { //freopen("test.txt", "r", stdin); scanf("%d", &n); int sum = 0; for (int i = 1; i <= n; i++) { scanf("%d", a + i); sum += a[i]; } sum /= n; s = n + 1, t = s + 1; for (int i = 1; i <= n; i++) { if (a[i] > sum) { add(s, i, a[i] - sum, 0); } else if(a[i]<sum){ add(i, t, sum - a[i], 0); } } for (int i = 1; i <= n; i++) { if (i != 1) { add(i, i - 1, inf, 1); } if (i != n) { add(i, i + 1, inf, 1); } } add(1, n, inf, 1); add(n, 1, inf, 1); mcmf(); printf("%lld\n", mincost); return 0; }