传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1061
尽管不是mcmf的裸题,但还是保存一下模版叭~
很好的一道建模的题,把变量间的加加减减等效成网络中的流入流量与流出流量,再带上个权,求个最小费用就好,详细题解间此:https://www.byvoid.com/blog/noi-2008-employee/
#include <cstdio> #include <cstring> #include <algorithm> const int maxn = 1010, maxm = 10005, maxe = 100000; const long long inf = 0x3c3c3c3c3c3c3c3cLL; int n, m, a[maxn], s[maxm], t[maxm], cost[maxm], S, T; int head[maxn], to[maxe], next[maxe], from[maxe], lb; long long d[maxn], c[maxn], w[maxe], flow[maxe], cap[maxe]; int p[maxn], que[maxn], head_, tail, h; bool inq[maxn]; inline bool spfa(long long & co) { memset(d, 0x3c, sizeof d); head_ = tail = 0; memset(inq, 0, sizeof inq); que[tail++] = S; inq[S] = 1; c[S] = inf; d[S] = 0; while (head_ != tail) { h = que[head_++]; inq[h] = 0; if (head_ == T + 3) { head_ = 0; } for (int j = head[h]; j != -1; j = next[j]) { if (cap[j] > flow[j] && d[to[j]] > d[h] + w[j]) { d[to[j]] = d[h] + w[j]; c[to[j]] = std::min(c[h], cap[j] - flow[j]); p[to[j]] = j; if (!inq[to[j]]) { que[tail++] = to[j]; inq[to[j]] = 1; if (tail == T + 3) { tail = 0; } } } } } if (d[T] == inf) { return false; } co += d[T] * c[T]; for (int i = T; i != S; i = from[p[i]]) { flow[p[i]] += c[T]; flow[p[i] ^ 1] -= c[T]; } return true; } inline long long mcmf(void) { long long co = 0; while (spfa(co)); return co; } inline void ist(int aa, int ss, long long ww, long long ca) { to[lb] = ss; from[lb] = aa; next[lb] = head[aa]; head[aa] = lb; w[lb] = ww; cap[lb] = ca; ++lb; to[lb] = aa; from[lb] = ss; next[lb] = head[ss]; head[ss] = lb; w[lb] = -ww; cap[lb] = 0; ++lb; } int main(void) { //freopen("in.txt", "r", stdin); memset(head, -1, sizeof head); memset(next, -1, sizeof next); scanf("%d%d", &n, &m); T = n + 2; for (int i = 1; i <= n; ++i) { scanf("%d", a + i); } for (int i = 1; i <= m; ++i) { scanf("%d%d%d", s + i, t + i, cost + i); } for (int i = 1; i <= n + 1; ++i) { if (a[i - 1] - a[i] >= 0) { ist(S, i, 0, (long long)(a[i - 1] - a[i])); } else { ist(i, T, 0, (long long)(a[i] - a[i - 1])); } } for (int i = 1; i <= m; ++i) { ist(t[i] + 1, s[i], (long long)cost[i], inf); } for (int i = 1; i <= n; ++i) { ist(i, i + 1, 0, inf); } printf("%lld ", mcmf()); return 0; }