• 【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;
    }
    
  • 相关阅读:
    Integer.highestOneBit(int i)方法的作用与底层实现
    一文搞明白位运算、补码、反码、原码
    Zookeeper如何解决脑裂问题
    Zookeeper请求处理原理分析
    Linux 设备驱动之 UIO 机制
    virtio guest side implementation: PCI, virtio device, virtio net and virtqueue
    DPDK之(八)——vhost库
    Red Hat OpenStack 10的新特性
    探秘DPDK Virtio的不同路径
    2017版:KVM 性能优化之内存优化
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11762083.html
Copyright © 2020-2023  润新知