【费用流】CF802C Heidi and Library (hard)

【题目】
CF
你有一个容量为 k k k的空书架,现在共有 n n n个请求,每个请求给定一本书 a i a_i ai,如果你的书架里没有这本书,你就必须以 w i w_i wi的价格购买这本书放入书架。当然,你可以在任何时候丢掉书架里的某本书。请求出完成这 n n n个请求所需要的最少价钱。
n , k ≤ 80 , w i ≤ 1 0 6 n,k\leq 80,w_i\leq 10^6 n,k80,wi106

【解题思路】
范围很小可以考虑网络流,有价格限制即考虑费用流。

对于第 i i i天,我们先强制要买一本书,那么连边 ( S , i , 1 , w a i ) (S,i,1,w_{a_i}) (S,i,1,wai)。由于一本书如果必须要丢,那么在什么时候丢都一样,于是接下来新建一排中转点来表示这天的物品丢不丢,那么连边 ( i , i + n , 1 , 0 ) (i,i+n,1,0) (i,i+n,1,0),表示这个物品不保留。还需要连 ( i + n , T , 1 , 0 ) (i+n,T,1,0) (i+n,T,1,0)表示只能丢一次。为满足至多保留 k − 1 k-1 k1本书的限制还要连 ( i , i + 1 , k − 1 , 0 ) (i,i+1,k-1,0) (i,i+1,k1,0)

对于一本书,若它之前已经在书架上,那么我们可以不买入,也可以看作卖出再买入,那么我们可以连 ( i − 1 , p r e a i + n , 1 , − w a i ) (i-1,pre_{a_i}+n,1,-w_{a_i}) (i1,preai+n,1,wai),表示在前一天卖出,同时会占用它到 T T T的边。

跑最小费用最大流即可。

复杂度 O ( c o s t f l o w ( n 2 , n 2 ) ) O(costflow(n^2,n^2)) O(costflow(n2,n2))

【参考代码】

#include<bits/stdc++.h>
using namespace std;

const int N=165,M=N*6,inf=0x3f3f3f3f;
int n,K,tot,S,T,ans;
int head[N],dis[N],inq[N],a[N],w[N],pre[N],ins[N];
queue<int>q;

struct Tway{int v,nex,w,c;}e[M];
void add(int u,int v,int w,int c)
{
	e[++tot]=(Tway){v,head[u],w,c};head[u]=tot;
	e[++tot]=(Tway){u,head[v],0,-c};head[v]=tot;
}

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

bool spfa()
{
	memset(dis,0x3f,(T+2)<<2);q.push(S);dis[S]=0;inq[S]=1;
	while(!q.empty())
	{
		int x=q.front();q.pop();inq[x]=0;
		for(int i=head[x];i;i=e[i].nex)
		{
			int v=e[i].v;
			if(e[i].w && dis[v]>dis[x]+e[i].c) 
			{
				dis[v]=dis[x]+e[i].c;
				if(!inq[v]) q.push(v),inq[v]=1;
			}
		}
	}
	return dis[T]<(inf/2);
}

int dfs(int x,int flow)
{
	if(x==T || !flow) return flow;
	int u,used=0;ins[x]=1;
	for(int i=head[x];i;i=e[i].nex)
	{
		int v=e[i].v;
		if(ins[v] || !e[i].w || (dis[v]!=dis[x]+e[i].c)) continue;
		u=dfs(v,min(e[i].w,flow-used));
		e[i].w-=u;e[i^1].w+=u;used+=u;ans+=e[i].c*u;
	}
	ins[x]=0;
	return used;
}

int main()
{
#ifdef Durant_Lee
	freopen("CF802C.in","r",stdin);
	freopen("CF802C.out","w",stdout);
#endif
	n=read();K=read();S=2*n+1;T=S+1;tot=1;
	for(int i=1;i<=n;++i) a[i]=read();
	for(int i=1;i<=n;++i) w[i]=read();
	for(int i=1;i<=n;++i)
	{
		add(S,i,1,w[a[i]]);add(i+n,T,1,0);add(i,i+n,1,0);
		if(i<n) add(i,i+1,K-1,0);
		if(pre[a[i]]) add(i-1,pre[a[i]]+n,1,-w[a[i]]);
		pre[a[i]]=i;
	}
	while(spfa()) dfs(S,inf);
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值