BZOJ1221: [HNOI2001] 软件开发

来源:互联网 发布:mysql忘记root密码重装 编辑:程序博客网 时间:2024/05/22 04:15

经典餐巾问题
最小费用最大流
每天拆成两个点代表出入度,左边点出度代表每天用完的毛巾的去向,右边点入度代表每天毛巾的来源,
源向左边每个点连边流量为这一天用掉的毛巾,费用0,
左边的点i可以向右边的i+a+1连边流量inf,费用fA,i+b+1连边流量inf,费用fB,代表这天用完后的毛巾消毒后拿到这一天用,
每天用完的毛巾可以不消毒堆积到下一天,所以左边的点i向i+1连边流量inf,费用0,
每天毛巾的来源可以是直接购买,所以源向右边的点连边流量inf,费用f,
最后右边的点向汇连边流量为每天的需要毛巾数,费用0

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9using namespace std;inline void down(int &x,const int y){if(x>y)x=y;}const int maxn = 11000;const int maxm = 21000;int n,m,st,ed;struct edge{    int y,c,d,nex;}a[maxm]; int len,fir[maxn];void ins(const int x,const int y,const int c,const int d){    a[++len].y=y; a[len].c=c; a[len].d=d;    a[len].nex=fir[x]; fir[x]=len;    a[++len].y=x; a[len].c=0; a[len].d=-d;    a[len].nex=fir[y]; fir[y]=len;}queue<int>q;int d[maxn],pos[maxn],pre[maxn];bool v[maxn];bool bfs(){    for(int i=1;i<=ed;i++) d[i]=inf; d[st]=0;    q.push(st);    while(!q.empty())    {        const int x=q.front(); q.pop(); v[x]=false;        for(int k=fir[x];k;k=a[k].nex) if(a[k].c)        {            const int y=a[k].y;            if(d[y]>d[x]+a[k].d)            {                d[y]=d[x]+a[k].d;                pos[y]=x; pre[y]=k;                if(!v[y]) v[y]=true,q.push(y);            }        }    }    return d[ed]!=inf;}int flow(){    int r=0;    while(bfs())    {        int k=inf;        for(int i=ed;i!=st;i=pos[i]) down(k,a[pre[i]].c);        r+=k*d[ed];        for(int i=ed;i!=st;i=pos[i])        {            a[pre[i]].c-=k; a[pre[i]^1].c+=k;        }    }    return r;}int main(){    len=1; memset(fir,0,sizeof fir);    int an,bn,f,fa,fb;    scanf("%d%d%d%d%d%d",&n,&an,&bn,&f,&fa,&fb);    st=2*n+1,ed=st+1; ins(st,1,inf,f);    for(int i=1;i<=n;i++)    {        int x; scanf("%d",&x);        ins(st,i,x,0); ins(i+n,ed,x,0);        ins(st,i+n,x,f);        if(i+1<=n) ins(i,i+1,inf,0);        if(i+an+1<=n) ins(i,i+an+1+n,inf,fa);        if(i+bn+1<=n) ins(i,i+bn+1+n,inf,fb);    }    printf("%d\n",flow());    return 0;}
0 0