Delight for a Cat
题解
网络流板子题。
通常的网络流是不会出现这种一个点有两个方向可以走的,而且这样也不大好处理。
于是,我们考虑差分建图。
先假设它选的全部都是睡觉,求出的值,再减去打隔膜的时间差。这样就成了一个常规的最小费用最大流。
因为连续k段中一定有个时间在睡觉,于是总流量为。于是限制源点流量为。
然后就是连续k段只有一定个被选的常规操作,从向连一条流量为1,边权为的边,也就是这一天改选打隔膜的时间差。若连出去了就连向汇点。从源点向1-k的点各连容量为1的边,保证区间大小,反正总流量不会超过。
为了限制下界为,我们还需在与间连一条容量为的边。因为到汇点的流一定是最大的,所以流肯定会在前面跑满甚至跑过它的下界,再在这里跑这条边。这样才能保证总流量是最大的,及源点的流一定是满的,再来满足总费用最小。这样就巧妙的实现了下界为,上界为。还需在第n个点向汇点连边,让还未跑的流流入汇点。
图就这样建好了,最后跑一遍网络流即可。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
#define int LL
const int INF=0x7f7f7f7f7f7f;
#define MAXN 5005
#define gc() getchar()
template<typename _T>
inline void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
int dis[MAXN],vis[MAXN],pre[MAXN];
int head[MAXN],tot,s1,t1;
int from[MAXN<<1],to[MAXN<<1];
int nxt[MAXN<<1],paid[MAXN<<1],cap[MAXN<<1];
void addEdge(int u,int v,int flow,int cost){
//printf("%d %d %d %d\n",u,v,flow,cost);
from[++tot]=u;to[tot]=v;paid[tot]=cost;
cap[tot]=flow;nxt[tot]=head[u];head[u]=tot;
}
void addedge(int u,int v,int flow,int cost){
//printf("%d %d %d %d\n",u,v,flow,cost);
addEdge(u,v,flow,cost);addEdge(v,u,0,-cost);
}
int EK(){
int res=0,sum=0;
while(1){
for(int i=0;i<=t1;i++) dis[i]=INF,vis[i]=0,pre[i]=-1;
queue<int> q;while(!q.empty()) q.pop();
dis[s1]=0;vis[s1]=1;q.push(s1);
while(!q.empty()){
int now=q.front();q.pop();vis[now]=0;
//printf("%d\n",now);
for(int i=head[now];~i;i=nxt[i]){
int v=to[i];//printf("%d-->%d %d %d %d\n",now,v,dis[now],cap[i],dis[v]);
if(cap[i]>0&&dis[v]>dis[now]+paid[i]){
//printf("%d-->%d\n",now,v);
dis[v]=dis[now]+paid[i];pre[v]=i;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
//printf("dis%d %d\n",res,dis[t1]);
if(dis[t1]>INF-1) return res;int minn=INF;
for(int i=pre[t1];~i;i=pre[from[i]])minn=min(minn,cap[i]);
for(int i=pre[t1];~i;i=pre[from[i]])cap[i]-=minn,cap[i^1]+=minn;
res+=dis[t1]*minn;sum+=minn;
//printf("%d %d %d\n",res,minn,dis[t]);
}
}
int n,k,T1,T2,sums;
int s[MAXN],e[MAXN];
signed main(){
memset(head,-1,sizeof(head));
read(n);read(k);read(T1);read(T2);s1=n+1;t1=n+3;tot=-1;
for(int i=1;i<=n;i++)read(s[i]),sums+=s[i];
for(int i=1;i<=n;i++)read(e[i]);
for(int i=1;i<=n;i++)addedge(i,i+k<=n?i+k:t1,1,s[i]-e[i]);
for(int i=1;i<=k;i++)addedge(n+2,i,INF,0);addedge(s1,n+2,k-T1,0);
for(int i=1;i<n;i++)addedge(i,i+1,k-T1-T2,0);addedge(n,t1,k-T1-T2,0);
printf("%lld\n",sums-EK());
for(int i=0;i<2*n;i+=2)
if(!cap[i])printf("E");
else printf("S");
return 0;
}