您的位置:首页 > 其它

_bzoj1061 [Noi2008]志愿者招募【最小费用最大流】

2016-12-14 20:03 429 查看

传送门: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\n", mcmf());
return 0;
}

  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: