[ARC137E] Baker

Problem Statement

Snuke runs a bakery. He is planning for the next $N$ days. Let us call these days Day $1,2,\cdots,N$.

At the moment, the bakery hires nobody. There are $M$ bakers that Snuke can hire, numbered $1$ to $M$.

$C_i$ yen must be paid to hire Baker $i$. If Baker $i$ is hired, they will work on Day $L_i, L_i+1, \cdots, R_i$, baking one loaf of bread each day.

For each $j$ ($1 \leq j \leq N$), there is a limit $A_j$ to the number of loaves of bread that can be sold on Day $j$. If $x_j$ loaves of bread are baked on Day $j$, $\min(x_j, A_j)$ loaves will be sold on that day.

Each loaf of bread sold will yield a profit of $D$ yen.

Snuke wants to choose the set of bakers to hire to maximize the final profit: $($The total number of loaves sold$) \times D - ($The total cost of hiring bakers$)$. Find the maximum possible value of this.

Constraints

  • $1 \leq N \leq 2000$
  • $1 \leq M \leq 2000$
  • $1 \leq D \leq 10^9$
  • $1 \leq A_j \leq M$
  • $1 \leq L_i \leq R_i \leq N$
  • $1 \leq C_i \leq 10^9$
  • All values in input are integers.
网络流中一条流量为 $f$,费用为 $w$ 的边在下文表示为 $(f,w)$

考虑把每天的限制在网络流的边上考虑。

那么 \(i->i+1\) 的点表示这天的情况,连一条 \((a_i,d)\) 的边和一条 \((\infin,0)\) 的边。

然后对于一个面包师,从 \(R_i+1\)\(L_i\) 连一条 \(-C_i\) 的边。

现在就要求他的最大费用循环流就行了。

全部取负,求最小费用循环流。

#include<bits/stdc++.h>
using namespace std;
const int N=2005,T=2004,INF=1e9;
int hd[N],e_num=1,n,m,d,v[N],p[N],g[N],a[N],l[N],r[N],c[N];
priority_queue<pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > >q;
long long ans,h[N],dis[N];
struct edge{
	int u,v,nxt,f,w;
}e[N*10];
void add_edge(int u,int v,int f,int w)
{
	e[++e_num]=(edge){u,v,hd[u],f,w};
	hd[u]=e_num;
	e[++e_num]=(edge){v,u,hd[v],0,-w};
	hd[v]=e_num;
}
void spfa()
{
	static int l,r,q[N];
	memset(h,0x3f,sizeof(h));
	v[q[l=r=1]=0]=1,h[0]=0;
	while(l<=r)
	{
		for(int i=hd[q[l%N]];i;i=e[i].nxt)
		{
			if(e[i].f&&h[e[i].v]>h[q[l%N]]+e[i].w)
			{
				h[e[i].v]=h[q[l%N]]+e[i].w;
				if(!v[e[i].v])
					v[q[(++r)%N]=e[i].v]=1;
			}
		}
		v[q[(l++)%N]]=0;
	}
}
int dijkstra()
{
	memset(dis,0x3f,sizeof(dis));
	memset(v,0,sizeof(v));
	q.push(make_pair(0,0));
	dis[0]=0;
	while(!q.empty())
	{
		int k=q.top().second;
		q.pop();
		if(v[k])
			continue;
		v[k]=1;
		for(int i=hd[k];i;i=e[i].nxt)
		{
			if(e[i].f&&dis[k]+e[i].w+h[k]-h[e[i].v]<dis[e[i].v])
			{
				assert(e[i].w+h[k]-h[e[i].v]>=0);
				dis[e[i].v]=dis[k]+e[i].w+h[k]-h[e[i].v];
				p[e[i].v]=i;
				q.push(make_pair(dis[e[i].v],e[i].v));
			}
		}
	}
	return v[T];
}
int main()
{
	scanf("%d%d%d",&n,&m,&d);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",l+i,r+i,c+i),g[l[i]]++,g[r[i]+1]--;
	for(int i=1;i<=n;i++)
	{
		g[i]+=g[i-1];
		if(g[i]<=a[i])
			add_edge(i,i+1,g[i],d);
		else
			add_edge(i,i+1,a[i],d),add_edge(i,i+1,g[i]-a[i],0);
		ans+=min(a[i],g[i])*1LL*d;
	}
	for(int i=1;i<=m;i++)
	{
		add_edge(0,l[i],1,0);
		add_edge(l[i],r[i]+1,1,c[i]);
		add_edge(r[i]+1,T,1,0);
	}
	spfa();
	int ret=0;
	while(dijkstra())
	{
		for(int i=0;i<=n+1;i++)
			h[i]=h[i]+dis[i];
		h[T]+=dis[T];
		int mnf=INF;
		for(int i=T;i;i=e[p[i]].u)
			mnf=min(mnf,e[p[i]].f);
		for(int i=T;i;i=e[p[i]].u)
			e[p[i]].f-=mnf,e[p[i]^1].f+=mnf;
		ret+=mnf;
		ans-=mnf*h[T];
	}
	printf("%lld",ans);
}

posted @ 2023-09-25 11:10  灰鲭鲨  阅读(17)  评论(0编辑  收藏  举报