CF802C Heidi and Library (hard)

题解

买进书有点麻烦..

我们考虑每天强制买进书

那么把书留到这一天,那么就等于在前一天卖了后,这一天又买回来,

卖出的价值为\(-C_{a[i]}\)

然后对每一天建两个点\(A,B\)

到了\(B\)点,就等于卖了这本书

然后\(A_i->A_{i+1}\)\((k-1,0)\)

因为强制买书,所以只有\(k-1\)本书流向这天

\(S->A_{i}\)\((1,C_{a[i] })\)

\(A_{i}->B_{i}\)\((1, 0)\)

\(B_i->T\)\((1,0)\)

记$pos[i] \(表示书\)i$上一次出现的位置

那么\(A_{i-1}->B_{pos[i]}\)\((1,-C_{a[i]})\)

然后跑最小费用最大流

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register

using namespace std;
template<class T> inline void read(T &x) {
    x = 0; RG char c = getchar(); bool f = 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    x = f ? -x : x;
    return ;
}
template<class T> inline void write(T x) {
    if (!x) {putchar(48);return ;}
    if (x < 0) x = -x, putchar('-');
    int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}

const int N = 210, M = 2000010, inf = 2147483647;

struct node {
    int to, nxt, w, v;
}g[M];
int last[N], gl = 1;
void add(int x, int y, int w, int v) {
    g[++gl] = (node) {y, last[x], w, v};
    last[x] = gl;
    g[++gl] = (node) {x, last[y], 0, -v};
    last[y] = gl;
}

int dis[N], s, t, pre[N], from[N];
bool vis[N];

queue<int> q;

inline bool spfa() {
    memset(dis, 127 / 3, sizeof(dis));
    dis[s] = 0;
    q.push(s);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = last[u]; i; i = g[i].nxt) {
            int v = g[i].to;
            if (dis[v] > dis[u] + g[i].v && g[i].w) {
                dis[v] = dis[u] + g[i].v;
                pre[v] = u; from[v] = i;
                if (!vis[v]) vis[v] = 1, q.push(v);
            }
        }
        vis[u] = 0;
    }
    return dis[0] != dis[t];
}

int a[85], c[85], n, k;

inline int Mcmf() {
    int res = 0;
    while (spfa()) {
        int di = inf;
        for (int i = t; i != s; i = pre[i]) di = min(di, g[from[i]].w);
        res += di * dis[t];
        for (int i = t; i != s; i = pre[i]) g[from[i]].w -= di, g[from[i] ^ 1].w += di;
    }
    return res;
}

int pos[85];

int main() {
    read(n), read(k);
    s = n * 2 + 1, t = s + 1;
    for (int i = 1; i <= n; i++) read(a[i]);
    for (int i = 1; i <= n; i++) read(c[i]);
    for (int i = 1; i <= n; i++) {
        add(s, i, 1, c[a[i]]);
        add(i + n, t, 1, 0);
        add(i, i + n, 1, 0);
        if (pos[a[i]]) add(i - 1, pos[a[i]] + n, 1, -c[a[i]]);
        pos[a[i]] = i;
    }
    for (int i = 1; i < n; i++)
        add(i, i + 1, k - 1, 0);
    printf("%d\n", Mcmf());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zzy2005/p/10481083.html