P1251 餐巾计划问题
一道特别棒的费用流好题,思路非常巧妙
对于每一天,我们分为早上和晚上两个节点
每天早上会消耗\(r_i\)条干净的毛巾,可以视为流向汇点,所以我们向汇点连一条流量为\(r_i\),费用为\(0\)的边
每天晚上会产生\(r_i\)条脏毛巾,可以视为从源点流出,所以我们从源点连一条流量为\(r_i\),费用为\(0\)的边
然后我们考虑以下四种情况:买毛巾,慢洗,快洗,留着攒味
首先是买毛巾,我们直接让毛巾从源点流向每个早上,所以从源点连一条流量无限大,费用为\(p\)的边
然后是慢洗,我们从每个晚上向\(n\)天之后的早上连一条流量无限大,费用为\(s\)的边,快洗处理方式类似
最后是保存,我们直接从每个晚上向下一个晚上连一条流量无限大,费用为\(0\)的边即可
以上所建的所有边都需要建对应的反边,这也是费用流的常规写法
图建好之后,这道题可以说已经做完了,写模板就是了
下面放代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#include<queue>
#define ll long long
#define gc getchar
#define maxn 4005
#define maxm 100005
using namespace std;
inline ll read(){
ll a=0;int f=0;char p=gc();
while(!isdigit(p)){f|=p=='-';p=gc();}
while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
return f?-a:a;
}int n,S,T,a,b,c,g,f;ll ans;
struct ahaha{
int f,w,to,next;
}e[maxm<<1];int tot,head[maxn];
inline void add(int u,int v,int w,int f){
e[tot]={f,w,v,head[u]};head[u]=tot++;
}
deque<int>q;
int bi[maxn],d[maxn],fl[maxn],la[maxn];
int spfa(){
memset(fl,63,sizeof fl);memset(d,63,sizeof d);
memset(bi,0,sizeof bi);d[S]=0;la[T]=-1;q.push_back(S);
while(!q.empty()){
int u=q.front();q.pop_front();bi[u]=0;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(d[v]<=d[u]+e[i].f||e[i].w<=0)continue;
d[v]=d[u]+e[i].f;la[v]=i;
fl[v]=min(fl[u],e[i].w);
if(bi[v])continue;bi[v]=1;
if(q.empty()||d[v]<d[q.front()])q.push_front(v);
else q.push_back(v);
}
}return ~la[T];
}
int main(){memset(head,-1,sizeof head);
n=read();S=0;T=n<<1|1;
for(int i=1;i<=n;++i){
int w=read();
add(S,i+n,w,0);add(i+n,S,0,0);
add(i,T,w,0);add(T,i,0,0);
}
for(int i=1;i<n;++i){
add(i+n,i+n+1,2147483647,0);
add(i+n+1,i+n,0,0);
}
a=read();b=read();c=read();g=read();f=read();
for(int i=1;i<=n;++i){
add(S,i,2147483647,a);
add(i,S,0,-a);
}
for(int i=n-b;i;--i){
add(i+n,i+b,2147483647,c);
add(i+b,i+n,0,-c);
}
for(int i=n-g;i;--i){
add(i+n,i+g,2147483647,f);
add(i+g,i+n,0,-f);
}
while(spfa()){
ans+=(ll)fl[T]*d[T];
int now=T;
while(now!=S){
e[la[now]].w-=fl[T];
e[la[now]^1].w+=fl[T];
now=e[la[now]^1].to;
}
}
printf("%lld\n",ans);
return 0;
}
所有文字著作权归本人所有,禁止转载抄袭,若盗版进行商业运营,本人必将追究到底。