CF802CHeidi and Library(网络流)
Posted heyuhhh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF802CHeidi and Library(网络流)相关的知识,希望对你有一定的参考价值。
题意:
给出(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;
}
以上是关于CF802CHeidi and Library(网络流)的主要内容,如果未能解决你的问题,请参考以下文章
CF802C Heidi and Library (hard)
CF802LSend the Fool Further! (hard) 高斯消元