CF802C Heidi and Library

1|0CF802C Heidi and Library

1|1题目描述:

Link

1|2题目分析:

看到这么小的数据范围直接想网络流(其实一开始想的搜索),看到题目中还有一个价值的限制,那么往费用流上面去想。

那么难点又来到了建图上,那么问题的难点就是如何去处理丢去那一本书架里面的书的问题。

我们可以发现一些性质:

如果 i 天和 j 天都用了同一本书,那么如果中间没有扔掉,那么只需要花费一本书的价格,反之要再买一次即花费两本书的价钱。那么假设我们在中间需要扔掉这本书的话,我们完全可以在 i 处卖掉,这样是完全不劣的。

那么利用费用流去解决这么一个每一天买还是不买的问题是非常的复杂的。所以说我们直接先把所有的书都买一遍,利用费用流去看某些书树不需要进行购买的。

那么如果说 i 天买的书留到了 j 天,那么我们可以在 j1 卖掉这本书,那么其实就可以看成在 j 天没有买书。

那么我们的模型就显现出来了。大致可以分为以下几步。

  1. 每一天都有两个节点 ii,从源点向每一天的 i 进行连容量为 1,边权是书的价格的边,表示这一天买了这本书。
  2. 每一个 ii 连一条容量为 1,费用为 0 的边,表示今天买完之后直接就卖掉了。
  3. 每一个 ii+1 连一条容量为 k1,费用为 0 的边,表示书的容量,书架最多能承受 k1 本书。
  4. 每一个 i1i 所拥有的书的种类的上一个点连一个容量为 1,边权为负的价格的边,表示卖掉这本书
  5. 每一个 i 向汇点连容量为 1,费用为 0 的边来统计扔的答案。

最后跑一边费用流即可。(建图真神奇

#include<bits/stdc++.h> #define g() getchar() #define il inline #define eps 1e-10 #define LL long long #define pa pair<int, int> #define for_1(i, n) for(int i = 1; i <= (n); ++i) #define for_0(i, n) for(int i = 0; i < (n); ++i) #define for_xy(i, x, y) for(int i = (x); i <= (y); ++i) #define for_yx(i, y, x) for(int i = (y); i >= (x); --i) #define for_edge(i, x) for(int i = head[x]; i; i = nxt[i]) // #define int long long #define DB double #define m_p make_pair #define p_b push_back #define fir first #define sec second // #define mid ((l + r) >> 1) using namespace std; const int N = 1e6 + 10; const int INF = 0x3f3f3f3f; const int mod = 1000000007; const int up = 259; inline int re() { int x = 0, p = 1; char ch = getchar(); while(ch > '9' || ch < '0') {if(ch == '-') p = -1; ch = getchar();} while(ch <= '9' and ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();} return x * p; } int head[N], ver[N], edge[N], tot = 1, nxt[N], cost[N]; il void add(int x, int y, int z, int co) {ver[++tot] = y; nxt[tot] = head[x]; head[x] = tot; edge[tot] = z; cost[tot] = co; } il void addedge(int x, int y, int z, int co ) {add(x, y, z, co); add(y, x, 0, -co); } //n^2 m int n, m, s, t, mincost, maxflow, k; int vis[N], incf[N], dis[N], pre[N]; queue<int> q; int a[N], b[N]; bool spfa() { memset(vis, 0, sizeof(vis)); memset(dis, 0x3f, sizeof(dis)); while(q.size()) q.pop(); q.push(s); incf[s] = 1LL<<30; vis[s] = 1; dis[s] = 0; while(q.size()) { int x = q.front(); q.pop(); vis[x] = 0; for_edge(i, x) { int y = ver[i], z = edge[i], co = cost[i]; if(dis[y] > dis[x] + co and z) { incf[y] = min(incf[x], z); dis[y] = dis[x] + co; pre[y] = i; if(!vis[y]) q.push(y); } } } return dis[t] != INF; } il void ML() { while(spfa()) { maxflow += incf[t]; mincost += incf[t] * dis[t]; int x = t; while(x) { int i = pre[x]; edge[i] -= incf[t]; edge[i ^ 1] += incf[t]; x = ver[i ^ 1]; } } } signed main() { n = re(), k = re(); for_1(i, n) a[i] = re(); for_1(i, n) b[i] = re(); s = 2 * n + 1; t = s + 1; for_1(i, n) addedge(s, i, 1, b[a[i]]); for_1(i, n) addedge(i, i + n, 1, 0); for(int i = 1; i < n; ++i) addedge(i, i + 1, k - 1, 0); for(int i = 2; i <= n; ++i) { for(int j = i - 1; j >= 1; --j) { if(a[j] == a[i]) {addedge(i - 1, j + n, 1, -b[a[i]]); break; } } } for(int i = 1; i <= n; ++i) addedge(i + n, t, 1, 0); ML(); cout<<mincost<<endl; }

__EOF__

本文作者Zwaire
本文链接https://www.cnblogs.com/Zwaire/p/16122502.html
关于博主:这个世界除了你,都知道我喜欢你
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Zwaire  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示