我A了这道题以后第一想做的事就是给自己两个大嘴巴子
我昨天晚上半夜写的题 结果我把spfa的vis[x]=0写大括号里面了
我今天还跟个弱智似的去找建图错哪了 真是僵硬
这道题本身还是挺水的 不过建图很有意思
以前去日照培训的时候讲过 但是没有写 过了好久了 就复习一下吧
每天要用多少餐巾是一定的
这道题建模的关键就是把每天需要用的餐巾和用完的餐巾分开考虑
每天用完的餐巾有三个去处
不作处理 留到下一天 送快洗 送慢洗
每天需要用的餐巾有三个来源
现买 从快洗送过来 从慢洗送过来
那么这道题的思路就非常清晰了
把第i天拆成两个点 Xi和Yi
这样连边(S,Yi,INF,p) (Xi,Y(i+m),INF,n) (Xi,Y(i+n),INF,s) (Xi,X(i+1),INF,0) (S,Xi,INF,0) (Yi,T,INF,0)
记得当时培训的时候想的是一个特别慢的建图方式
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N0=205,INF=1e9,N=N0*2,M=N*12,S=N-1,T=N-2;
int n=0;
int r[N0];
int p=0,m=0,f0=0,n0=0,s=0;
int head[N],to[M],next[M],from[M],c[M],f[M],cost[M],edge=0;
int q[M],front=0,back=0,vis[N],fr[N],dis[N];
inline void addEdge(int u,int v,int ac,int acost) {
to[edge]=v,from[edge]=u,cost[edge]=acost,c[edge]=ac,next[edge]=head[u],head[u]=edge++;
to[edge]=u,from[edge]=v,cost[edge]=-acost,c[edge]=0,next[edge]=head[v],head[v]=edge++;
}
inline void build() {
for (int i=1;i<=n;++i) {
addEdge(S,2*i,INF,p);
addEdge(S,2*i-1,r[i],0);
addEdge(2*i,T,r[i],0);
if (i!=n)
addEdge(2*i-1,2*(i+1)-1,INF,0);
if (i+m<=n)
addEdge(2*i-1,2*(i+m),INF,f0);
if (i+n0<=n)
addEdge(2*i-1,2*(i+n0),INF,s);
}
}
inline int spfa() {
front=back=0;
memset(vis,0,sizeof(vis));
memset(fr,-1,sizeof(fr));
for (int i=1;i<N;++i)
dis[i]=INF;
dis[S]=0;
vis[S]=1;
q[back++]=S;
while (front<back) {
int x=q[front++];
for (int e=head[x];~e;e=next[e]) {
int v=to[e];
if (dis[x]+cost[e]<dis[v] && c[e]>f[e]) {
dis[v]=dis[x]+cost[e];
fr[v]=e;
if (!vis[v]) {
vis[v]=1;
q[back++]=v;
}
}
}
vis[x]=0;
}
return dis[T]!=INF;
}
inline int augment() {
int mnc=INF,ret=0;
for (int e=fr[T];~e;e=fr[from[e]])
mnc=min(mnc,c[e]-f[e]);
for (int e=fr[T];~e;e=fr[from[e]]) {
ret+=mnc*cost[e];
f[e]+=mnc;
f[e^1]-=mnc;
}
return ret;
}
inline int mcf() {
int ret=0;
while (spfa())
ret+=augment();
return ret;
}
int main(void) {
freopen("napkin.in","r",stdin);
freopen("napkin.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",r+i);
scanf("%d%d%d%d%d",&p,&m,&f0,&n0,&s);
memset(head,-1,sizeof(head));
build();
printf("%d\n",mcf());
fclose(stdin);
fclose(stdout);
return 0;
}