P4016 负载平衡问题 网络流重温
P4016 负载平衡问题
这个题目现在第二次做,感觉没有这么简单,可能是我太久没有写这种题目了,基本上都忘记了,所以我连这个是费用流都没有看出来。
有点小伤心,知道是费用流之后,我居然还拆点了。
这个写完之后确实感觉没有那么难,但是写的过程还是很艰辛的,这个为什么是一个费用流呢,
因为我们知道每移动一个单位的货物,就会产生一单位的费用,所以这个就是费用流。
再而为什么这个不要拆点呢,因为每一个点都是只有一种属性,要么就是多了要输出,要么就是少了要进入,这个其实我也有点不是很清楚。
还没有完全弄明白。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <string> #include <iostream> #include <vector> #define inf 0x3f3f3f3f using namespace std; const int maxn = 3e5 + 10; typedef long long ll; struct edge { int u, v, c, f, cost; edge(int u=0,int v=0,int c=0,int f=0,int cost=0):u(u),v(v),c(c),f(f),cost(cost){} }; vector<edge>e; vector<int>G[maxn]; int a[maxn], p[maxn], inq[maxn], d[maxn], n, m; void init(int n) { for (int i = 0; i <= n; i++) G[i].clear(); e.clear(); } void addedge(int u,int v,int c,int cost) { e.push_back(edge(u, v, c, 0, cost)); e.push_back(edge(v, u, 0, 0, -cost)); int m = e.size(); G[u].push_back(m - 2); G[v].push_back(m - 1); } bool spfa(int s,int t,int &flow,ll &cost) { memset(d, inf, sizeof(d)); memset(inq, 0, sizeof(inq)); d[s] = 0, inq[s] = 1; p[s] = 0, a[s] = inf; queue<int>que; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); inq[u] = 0; for(int i=0;i<G[u].size();i++) { edge &now = e[G[u][i]]; int v = now.v; if(now.c>now.f&&d[v]>d[u]+now.cost) { d[v] = d[u] + now.cost; p[v] = G[u][i]; a[v] = min(a[u], now.c - now.f); if (!inq[v]) que.push(v), inq[v] = 1; } } } if (d[t] == inf) return false; flow += a[t]; cost += d[t] * 1ll * a[t]; for(int u=t;u!=s;u=e[p[u]].u) { e[p[u]].f += a[t]; e[p[u] ^ 1].f -= a[t]; } return true; } int MincostMaxflow(int s,int t,ll &cost) { cost = 0; int flow = 0; while (spfa(s, t, flow, cost)); return flow; } int main() { int n, sum = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum += a[i]; sum /= n; int s = 0, t = n + 1; for(int i=1;i<=n;i++) { if (a[i] > sum) addedge(s, i, a[i] - sum, 0); else addedge(i, t, sum - a[i], 0); if(i==1) { addedge(1, 2, inf, 1); addedge(1, n, inf, 1); } else if(i==n) { addedge(n, 1, inf, 1); addedge(n, n - 1, inf, 1); } else { addedge(i, i + 1, inf, 1); addedge(i, i - 1, inf, 1); } } ll ans = 0; MincostMaxflow(s, t, ans); printf("%lld\n", ans); return 0; }