[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.
考虑把每天的限制在网络流的边上考虑。
那么 \(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);
}