屯板子,以餐巾计划问题为例。
根据上下界网络流的一般做法,可以得知这里如果minf=0那么就是一般的网络流的边。
否则
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<queue>
#define N 4020
#define M 15*N
#define P(x) x
#define Q(x) (x+n)
#define inf INT_MAX
#define INF LLONG_MAX
#define lint long long
using namespace std;
struct edges{
int from,to,pre,resf,cost;
}e[M];int etop,h[N];
inline int add_edge(int u,int v,int f,int c)
{
e[++etop].from=u,e[etop].to=v,e[etop].pre=h[u];
return e[etop].resf=f,e[etop].cost=c,h[u]=etop;
}
inline int build_edge(int u,int v,int f,int c)
{
return add_edge(u,v,f,c),add_edge(v,u,0,-c);
}
lint d[N];bool inq[N];int fr[N];queue<int> q;
inline int spfa(int s,int t,int &flow,lint &cost)
{
for(int i=1;i<=t;i++) d[i]=INF;
memset(inq,false,sizeof(inq));
memset(fr,0,sizeof(fr));
while(!q.empty()) q.pop();
q.push(s),inq[s]=true,d[s]=0;
while(!q.empty())
{
int x=q.front();q.pop(),inq[x]=false;
for(int i=h[x],y;i;i=e[i].pre)
if(e[i].resf&&d[y=e[i].to]>d[x]+e[i].cost)
{
d[y]=d[x]+e[i].cost,fr[y]=i;
if(!inq[y]) inq[y]=true,q.push(y);
}
}
if(!fr[t]) return false;int minf=inf;
for(int i=fr[t];i;i=fr[e[i].from])
minf=min(minf,e[i].resf);
for(int i=fr[t];i;i=fr[e[i].from])
e[i].resf-=minf,e[((i-1)^1)+1].resf+=minf;
cost+=d[t]*minf,flow+=minf;return true;
}
int main()
{
int n;scanf("%d",&n);
int s=2*n+1,t=s+1;
// build_edge(t,s,inf,0);
for(int i=1;i<=n;i++)
{
int r;scanf("%d",&r);
build_edge(s,Q(i),r,0);
build_edge(P(i),t,r,0);
}
int p,x,y,a,b;
scanf("%d%d%d%d%d",&p,&x,&a,&y,&b);
for(int i=1;i<=n;i++)
{
build_edge(s,P(i),inf,p);
if(i+x<=n) build_edge(Q(i),P(i+x),inf,a);
if(i+y<=n) build_edge(Q(i),P(i+y),inf,b);
}
for(int i=1;i<n;i++) build_edge(P(i),P(i+1),inf,0);
int f=0;lint c=0;
while(spfa(s,t,f,c));
cout<<c<<endl;return 0;
}