BZOJ 1221: [HNOI2001] 软件开发 最小费用最大流

来源:互联网 发布:大连美工培训班哪里好 编辑:程序博客网 时间:2024/05/14 04:04

Description

某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。
Input

第1行为n,a,b,f,fA,fB. 第2行为n1,n2,……,nn. (注:1≤f,fA,fB≤60,1≤n≤1000)
Output

最少费用
Sample Input
4 1 2 3 2 1

8 2 1 6

Sample Output
38

解法:

copy了一个建图http://www.cnblogs.com/BLADEVIL/p/3470508.html

首先我们把一天拆成两个点,XI,YI,分别代表这一天买了多少

和洗多少,再加入源和汇S,T

1.每一天我们可以买新的毛巾,所以连接一条从S到XI的边,流量为正无穷(因为可以买好多),费用为f

2.然后我们对于买来的毛巾可以洗,每天都产生need[i]的毛巾可以洗,那么连一条从S到YI的边,

流量为need[i],费用为0(因为只决定要洗,没有确定洗的方案,所以先不算费用)

3.每一条要用a方法洗的毛巾,我们连一条从YI到X(I+a+1)的边,流量为正无穷(下文解释),费用为fa的

4.每一条要用b方法洗的毛巾,我们连一条从YI到X(I+b+1)的边,流量为正无穷(下文解释),费用为fb的

5.因为每天剩下的毛巾,我们可以不当天洗,所以连接一条从YI到Y(I+1)的边,流量为正无穷,费用为0(所以每天可以洗

的毛巾的个数是可能会很多的,4,5建的边流量要是正无穷)

6.那么我们每天买的毛巾除了洗,还可以不洗,也就是直接扔掉,所以连一条XI到T的边,流量为need[i],费用为0

//BZOJ 1221#include <bits/stdc++.h>using namespace std;const int inf = 0x3FFFFFFF;const int maxn = 2222;struct node{    int st, en, flow, cost, next;    node(){}    node(int st, int en, int flow, int cost, int next):st(st),en(en),flow(flow),cost(cost),next(next){}}E[101000];int num, p[maxn];void init(){    memset(p, -1, sizeof(p));    num = 0;}void add(int st, int en, int flow, int cost){    E[num] = node(st, en, flow, cost, p[st]);    p[st] = num++;    E[num] = node(en, st, 0, -cost, p[en]);    p[en] = num++;}int pre[maxn];int dis[maxn];bool fg[maxn];bool spfa(int st, int en){    for(int i=0;i<=en;i++){        fg[i] = 0, dis[i] = inf, pre[i]=-1;    }    queue<int>q;    q.push(st);    fg[st]=1;    dis[st]=0;    while(!q.empty()){        int u = q.front(); q.pop();        fg[u]=0;        for(int i=p[u];~i;i=E[i].next){            int v = E[i].en;            if(E[i].flow&&dis[v]>dis[u]+E[i].cost){                dis[v] = dis[u]+E[i].cost;                pre[v]=i;                if(!fg[v]){                    fg[v]=1;                    q.push(v);                }            }        }    }    if(dis[en] < inf) return 1;    return 0;}int solve(int st, int en){    int ans=0;    while(spfa(st,en)){        int d = inf;        for(int i=pre[en];i+1;i=pre[E[i].st]) d = min(d, E[i].flow);        for(int i=pre[en];i+1;i=pre[E[i].st]){            E[i].flow -= d;            E[i^1].flow += d;            ans += d*E[i].cost;        }    }    return ans;}int n, a, b, f, fa, fb, S, T;int main(){    cin >> n >> a >> b >> f >> fa >> fb;    S = 2*n+1, T = S + 1;    init();    for(int i=1;i<=n;i++){        int x;        scanf("%d", &x);        add(S, i, x, 0);        add(i+n, T, x, 0);        add(S, i+n, inf, f);        if(i+a+1<=n) add(i,i+n+a+1,inf,fa);        if(i+b+1<=n) add(i,i+n+b+1,inf,fb);        if(i+1<=n) add(i,i+1,inf,0);    }    int ans = solve(S,T);    cout<<ans<<endl;    return 0;}
0 0
原创粉丝点击