【CF802C】Heidi and Library(网络流)

codeforces

题意:
给出(a_i)表示第(i)天需要(a_i),一开始为(0)
同时给出(c_i)表示购买(i)需要(c_i)的花费。
现在一天最多拥有物品(k)个,如果目前有(k)个了,要加入一个,则需推掉一个,下次则需重新购买。
问满足所有的需求的最小花费为多少。

思路:

  • 显然,第(i)天必须要有物品(a_i)
  • 直接考虑不好考虑,我们可以先让每天都购买(a_i),满足硬性条件后,再在适当时候补偿以使答案更优。
  • 显然购买(a_i)之后要么卖掉,要么留到下一次用。
  • 那么我们将一个点拆为:(i,i'),然后连接(S->i),流量为(1),费用为(c[i]);连接(i->i'),流量为(1),费用为(0);连接(i'->T),流量为(1),费用为(0)。表示每天都购买,并且直接卖掉。
  • 之后连接(i->i+1),流量为(k-1),费用为(0),表示这本书留到后面。
  • 显然如果(a_i=a_j)且在(i)这个位置留到(j)的话,那么在流网络中一定能够留到(j-1)这个位置,那么我们连边(j-1->i'),流量为(1),费用为(-c[i]),用来弥补费用。

代码如下:

/*
 * Author:  heyuhhh
 * Created Time:  2019/10/29 21:52:13
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 505, M = 2005;

struct E {
    int from, to, cp, v;
    E() {}
    E(int f, int t, int cp, int v) : from(f), to(t), cp(cp), v(v) {}
};

struct MCMF {
    int n, m, s, t;
    vector<E> edges;
    vector<int> G[N];
    bool inq[N];
    int d[N], p[N], a[M];

    void init(int _n, int _s, int _t) {
        n = _n; s = _s; t = _t;
        for(int i = 0; i <= n; i++) G[i].clear();
        edges.clear(); m = 0;
    }

    void addedge(int from, int to, int cap, int cost) {
        edges.emplace_back(from, to, cap, cost);
        edges.emplace_back(to, from, 0, -cost);
        G[from].push_back(m++);
        G[to].push_back(m++);
    }

    bool BellmanFord(int &flow, int &cost) {
        for(int i = 0; i <= n; i++) d[i] = INF;
        memset(inq, 0, sizeof inq);
        d[s] = 0, a[s] = INF, inq[s] = true;
        queue<int> Q; Q.push(s);
        while (!Q.empty()) {
            int u = Q.front(); Q.pop();
            inq[u] = false;
            for (int& idx: G[u]) {
                E &e = edges[idx];
                if (e.cp && d[e.to] > d[u] + e.v) {
                    d[e.to] = d[u] + e.v;
                    p[e.to] = idx;
                    a[e.to] = min(a[u], e.cp);
                    if (!inq[e.to]) {
                        Q.push(e.to);
                        inq[e.to] = true;
                    }
                }
            }
        }
        if (d[t] == INF) return false;
        flow += a[t];
        cost += a[t] * d[t];
        int u = t;
        while (u != s) {
            edges[p[u]].cp -= a[t];
            edges[p[u] ^ 1].cp += a[t];
            u = edges[p[u]].from;
        }
        return true;
    }

    int go() {
        int flow = 0, cost = 0;
        while (BellmanFord(flow, cost));
        return cost;
    }
} MM;

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

void run(){
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) cin >> c[i];
    int S = 0, T = 2 * n + 1;
    MM.init(T + 1, S, T);
    for(int i = 1; i <= n; i++) MM.addedge(S, i, 1, c[a[i]]);
    for(int i = 1; i <= n; i++) {
        MM.addedge(i, i + n, 1, 0);
        if(i < n) MM.addedge(i, i + 1, k - 1, 0);
        MM.addedge(i + n, T, 1, 0);
    }
    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n; j++) {
            if(a[i] == a[j]) {
                MM.addedge(j - 1, i + n, 1, -c[a[i]]);
            }
        }
    }
    int ans = MM.go();
    cout << ans << '
';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n >> k) run();
	return 0;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/11762083.html