CF802C Heidi and Library (hard) 最小费用流
你有一个容量为k的空书架,现在共有n个请求,每个请求给定一本书ai,如果你的书架里没有这本书,你就必须以ci的价格购买这本书放入书架。
当然,你可以在任何时候丢掉书架里的某本书。请求出完成这n个请求所需要的最少价钱。
做法1:
把每个请求拆成两个点 A,B
A表示买入 B表示卖出
addedge(S,A,1,c[a[i]]) addedge(A,B,1,0) addedge(B,T,1,0) 这样最大流必是n
每天的A向下一天的A连流量为k-1,费用为0的边,表示可以不扔,留到明天,但明天的书还需要一个位置,所以是k-1。
每天的前一天向上一个书出现的位置的B连一条费用为−c[a[i]],流量为1的边,表示在已经有这本书的情况下,可以卖掉这本书
跑一遍最小费用即为答案
#include <cstdio>
#include <queue>
#include <cstring>
#define INF 2147483647
using namespace std;
const int MAXN = ;
const int MAXM = ;
queue <int> q;
int s, t, now, n;
struct Edge{
int from, next, to, rest, cost;
}e[MAXM];
int head[MAXN], num = , dis[MAXN], vis[MAXN], Flow[MAXN], pre[MAXN];
inline void Add(int from, int to, int flow, int cost){
e[++num] = (Edge){ from, head[from], to, flow, cost }; head[from] = num;
e[++num] = (Edge){ to, head[to], from, , -cost }; head[to] = num;
}
int RoadsExist(){
q.push(s);
memset(dis, , sizeof dis);
dis[s] = ; Flow[s] = INF; pre[t] = ;
while(!q.empty()){
now = q.front(); q.pop(); vis[now] = ;
for(int i = head[now]; i; i = e[i].next)
if(e[i].rest && dis[e[i].to] > dis[now] + e[i].cost){
dis[e[i].to] = dis[now] + e[i].cost;
pre[e[i].to] = i;
Flow[e[i].to] = min(Flow[now], e[i].rest);
if(!vis[e[i].to]){
vis[e[i].to] = ;
q.push(e[i].to);
}
}
}
return pre[t];
}
int k, maxflow, mincost, sum;
int a[MAXN], c[MAXN], last[MAXN];
int main(){
scanf("%d%d", &n, &k); s = ; t = ;
for(int i = ; i <= n; ++i) scanf("%d", &a[i]);
for(int i = ; i <= n; ++i) scanf("%d", &c[i]);
for(int i = ; i <= n; ++i){
Add(s, i, , c[a[i]]);
if(i != ) Add(i - , i, k - , );
Add(i, i + n, , );
if(last[a[i]]) Add(i - , last[a[i]] + n, , -c[a[i]]);
Add(i + n, t, , );
last[a[i]] = i;
}
while(RoadsExist()){
mincost += Flow[t] * dis[t];
for(int i = t; i != s; i = e[pre[i]].from){
e[pre[i]].rest -= Flow[t];
e[pre[i] ^ ].rest += Flow[t];
}
}
printf("%d\n", mincost);
return ;
}
做法2:
把每个请求拆成两个点 A,B
A表示买入 B表示卖出
addedge(S,A,1,c[a[i]]) addedge(A,B,1,-INF) addedge(B,T,1,0) 这样最大流同样是n
然后n2遍历每个点对 如果书类型相同则addedge(Bi,Aj,1,0)表示这本书可以给第j个用
类型不同则addedge(Bi,Aj,1,c[a[j]]) 表示花这么多钱买入
然后跑min(n,k)次 SPFA 得到的费用即为答案(也可以拆S点来限制流量)
为什么要跑min(n,k)次的原因我认为是对于容量为min(n,k)的书架 其实你就是要选择min(n,k)个起始书 之后寻找最短路的最优方案即为寻找换书的最优方案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAX 85
const int inf=1e7;
inline int read()
{
int x=;bool t=false;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
return t?-x:x;
}
namespace MCMF
{
const int MAXM=,MAXN=;
struct Line{int v,next,w,fy;}e[MAXM];
int h[MAXN],cnt=;
inline void Add(int u,int v,int w,int fy)
{
e[cnt]=(Line){v,h[u],w,fy};h[u]=cnt++;
e[cnt]=(Line){u,h[v],,-fy};h[v]=cnt++;
}
int dis[MAXN],pe[MAXN],pv[MAXN],Cost,Flow;
bool vis[MAXN];queue<int> Que;
int S=MAXN-,T=MAXN-;
bool SPFA()
{
memset(dis,,sizeof(dis));dis[S]=;
Que.push(S);vis[S]=true;
while(!Que.empty())
{
int u=Que.front();Que.pop();
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(!e[i].w)continue;
if(dis[u]+e[i].fy<dis[v])
{
dis[v]=dis[u]+e[i].fy;pe[v]=i,pv[v]=u;
if(!vis[v])vis[v]=true,Que.push(v);
}
}
vis[u]=false;
}
if(dis[T]>=1e9)return false;
int flow=1e9;
for(int i=T;i!=S;i=pv[i])flow=min(flow,e[pe[i]].w);
for(int i=T;i!=S;i=pv[i])e[pe[i]].w-=flow,e[pe[i]^].w+=flow;
Flow+=flow;Cost=min(Cost,Cost+dis[T]*flow);
return true;
}
}
using namespace MCMF;
int n,K,a[MAX],c[MAX];
int main()
{
n=read();K=read();
for(int i=;i<=n;++i)a[i]=read();
for(int i=;i<=n;++i)c[i]=read();
for(int i=;i<=n;++i)Add(S,i,,c[a[i]]);
for(int i=;i<=n;++i)Add(i,i+n,,-inf);
for(int i=;i<=n;++i)Add(i+n,T,,);
for(int i=;i<=n;++i)
for(int j=i+;j<=n;++j)
Add(i+n,j,,a[i]==a[j]?:c[a[j]]);
Cost+=n*inf;K=min(K,n);while(K--)SPFA();
printf("%d\n",Cost);
return ;
}
CF802C Heidi and Library (hard) 最小费用流的更多相关文章
- 题解-CF802C Heidi and Library (hard)
题面 CF802C Heidi and Library (hard) 有一个大小为 \(k\) 的空书架.有 \(n\) 天和 \(n\) 种书,每天要求书架中有书 \(a_i\).每天可以多次买书, ...
- CF802C Heidi and Library hard 费用流 区间k覆盖问题
LINK:Heidi and Library 先说一下简单版本的 就是权值都为1. 一直无脑加书 然后发现会引起冲突,可以发现此时需要扔掉一本书. 扔掉的话 可以考虑扔掉哪一本是最优的 可以发现扔掉n ...
- CF802C Heidi and Library (hard)
题目描述 你有一个容量为k的空书架,现在共有n个请求,每个请求给定一本书ai,如果你的书架里没有这本书,你就必须以ci的价格购买这本书放入书架.当然,你可以在任何时候丢掉书架里的某本书.请求出完成这n ...
- 【CF802C】Heidi and Library(网络流)
[CF802C]Heidi and Library(网络流) 题面 CF 洛谷 题解 前面两个Easy和Medium都是什么鬼玩意啊.... 不难发现如果这天的要求就是第\(a_i\)种书的话,那么\ ...
- 【CF802C】Heidi and Library (hard) 费用流
[CF802C]Heidi and Library (hard) 题意:有n个人依次来借书,第i人来的时候要求书店里必须有种类为ai的书,种类为i的书要花费ci块钱购入.而书店的容量只有k,多余的书只 ...
- C. Heidi and Library (神奇的网络流)
C. Heidi and Library 题意 有 n 种分别具有价格 b 的书 a ,图书馆里最多同时存放 k 本书,已知接下来 n 天每天都有一个人来看某一本书,如果图书馆里没有则需要购买,问最少 ...
- 贪心算法 Heidi and Library (easy)
A. Heidi and Library (easy) time limit per test 2 seconds memory limit per test 256 megabytes input ...
- 【CF802C】 Heidi and Library (hard)(费用流)
题目链接 感觉跟餐巾计划问题有点像.费用流. 决定每天买不买不太好搞,不如先把所有东西都买进来,再卖掉不必要的. 拆点,每个点拆成\(x,y\). 源点向每个点的\(x\)连费用为当天的价格,流量为1 ...
- 【贪心】codeforces B. Heidi and Library (medium)
http://codeforces.com/contest/802/problem/B [题意] 有一个图书馆,刚开始没有书,最多可容纳k本书:有n天,每天会有人借一本书,当天归还:如果图书馆有这个本 ...
随机推荐
- 《Fluid Engine Development》 学习笔记2-基础
断断续续花了一个月,终于把这本书的一二两章啃了下来,理解流体模拟的理论似乎不难,无论是<Fluid Simulation for Computer Graphics>还是<计算流体力 ...
- 物联网防火墙himqtt源码之MQTT协议分析
物联网防火墙himqtt源码之MQTT协议分析 himqtt是首款完整源码的高性能MQTT物联网防火墙 - MQTT Application FireWall,C语言编写,采用epoll模式支持数十万 ...
- iCMSv7.0.15后台database.admincp文件仍存在SQL注入漏洞
闲着无聊,国庆时间没事做,又在Q群看到这种公告,只好下个icms慢慢玩.(PS:医院和学校居然都关网站了) 无奈自己太菜,审不出问题.只好上网百度icms之前的漏洞.然后居然成功在iCMSv7.0.1 ...
- 【C/C++开发】ffplay中的FrameQueue的自我理解
最近在研究ffplay,以下是本人今天在研究FrameQueue的时候整理的笔记,如有错误还请有心人指出来~ //这个队列是一个循环队列,windex是指其中的首元素,rindex是指其中的尾部元素. ...
- Net上传文件
Net上传文件 最近工作内容涉及到一点前端的内容,把学习到的内容记录下来,在今后的开发过程中,不要犯错.本篇只针对一些刚入职的小白及前端开发人员,大牛请绕道!~ 刚开始我们先不讲上传文件的防范问题,先 ...
- selenium + python 环境配置 (三)之启动chrome
安装启动chromedriver的方法和ie类似 2.启动chrome 即selenium调用ChromeDriver打开Chrome浏览器 ①下载并解压,你会得到一个chromedriver.exe ...
- hdoj3746(kmp算法的nex数组求最小循环节)
题目链接:https://vjudge.net/problem/HDU-3746 题意:给定一个字符串,问最少在两端添加多少元素使得整个字符串是呈周期性的. 思路: 应用到kmp中nex数组的性质,数 ...
- [转帖]Linux中awk工具的使用
Linux中awk工具的使用 2018年10月09日 17:26:20 谢公子 阅读数 2170更多 分类专栏: linux系统安全 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权 ...
- Word 查找替换高级玩法系列之 -- 段首批量添加字符
打开「查找和替换」输入框,按照下图操作: 更多查找替换高级玩法,参看:Word查找替换高级玩法系列 -- 目录篇 未完 ...... 点击访问原文(进入后根据右侧标签,快速定位到本文)
- 通过getAdaptiveExtension生成的动态类
通过getAdaptiveExtension生成的动态类 方便调式使用 请放在根目录下