[HNOI 2001]软件开发

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

题解

经典构图题。

将每一天拆成两个点$i$,$i’$,

加如下$6$条边:

$(sta, i, ni, f)$——在第$i$天可以买至多$ni$个餐巾,每块$f$分;

$(i, fin, ni, 0)$——第$i$天要用$ni$块餐巾;

$(sta, i’, ni, 0)$——第$i$天用剩的$ni$块旧餐巾;

$(i’, i+a+1, ∞, fa)$——第$i$天的旧餐巾送到快洗部,每块$fa$分;

$(i’, i+b+1, ∞, fb)$——第$i$天的旧餐巾送到慢洗部,每块$fb$分;

$(i’, i’+1, ∞, 0)$——第$i$天的旧餐巾可以留到第$i+1$天再处理;

求一次最小费用流即为结果。

 1 #include <set>
 2 #include <map>
 3 #include <ctime>
 4 #include <cmath>
 5 #include <queue>
 6 #include <stack>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <string>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 #define LL long long
15 #define Max(a, b) ((a) > (b) ? (a) : (b))
16 #define Min(a, b) ((a) < (b) ? (a) : (b))
17 using namespace std;
18 const int N = 2e3;
19 const int INF = ~0u>>1;
20 
21 int n,a,b,f,fa,fb,ni;
22 struct tt{
23     int to, cost, next, cap;
24 }edge[N*6+5];
25 int path[N+5], top = -1;
26 void Add(int u, int v, int cap, int cost);
27 int sta, fin;
28 int min_cost_flow();
29 int SPFA();
30 
31 int main(){
32     memset(path, -1, sizeof(path));
33     scanf("%d%d%d%d%d%d", &n, &a, &b, &f, &fa, &fb);
34     sta = 0, fin = 2*n+1;
35     for (int i = 1; i <= n; i++){
36       scanf("%d", &ni);
37       Add(sta, i, ni, f);
38       Add(i, fin, ni, 0);
39       Add(sta, i+n, ni, 0);
40       if (i+a+1 <= n) Add(i+n, i+a+1, INF, fa);
41       if (i+b+1 <= n) Add(i+n, i+b+1, INF, fb);
42       if (i+1 <= n) Add(i+n, i+1+n, INF, 0);
43     }
44     printf("%d
", min_cost_flow());
45     return 0;
46 }
47 
48 void Add(int u, int v, int cap, int cost){
49     edge[++top].to = v;
50     edge[top].cost = cost;
51     edge[top].cap = cap;
52     edge[top].next = path[u];
53     path[u] = top;
54     edge[++top].to = u;
55     edge[top].cost = -cost;
56     edge[top].cap = 0;
57     edge[top].next = path[v];
58     path[v] = top;
59 }
60 int min_cost_flow(){
61     int tolcost = 0;
62     int tmp;
63     while (tmp = SPFA()) tolcost += tmp;
64     return tolcost;
65 }
66 int SPFA(){
67     int dist[N+5];
68     memset(dist, 127/3, sizeof(dist)); dist[sta] = 0; dist[fin] = INF;
69     bool vis[N+5] = {0}; vis[sta] = 1;
70     queue<int>Q;
71     while (!Q.empty()) Q.pop();
72     Q.push(sta);
73     int pre[N+5] = {0};
74     while (!Q.empty()){
75       int u = Q.front(); Q.pop(); vis[u]=0;
76       for (int i = path[u]; i != -1; i = edge[i].next){
77           int v = edge[i].to;
78           if (dist[v] > dist[u]+edge[i].cost && edge[i].cap > 0){
79             dist[v] = dist[u]+edge[i].cost;
80             pre[v] = i;
81             if (!vis[v]){
82                 vis[v] = 1;
83                 Q.push(v);
84             }
85           }
86       }
87     }
88     if (dist[fin] == INF) return 0;
89     int minflow = INF;
90     for (int i = fin; i != sta; i = edge[pre[i]^1].to)
91       minflow = Min(minflow, edge[pre[i]].cap);
92     for (int i = fin; i != sta; i = edge[pre[i]^1].to)
93       edge[pre[i]].cap -= minflow,
94       edge[pre[i]^1].cap += minflow;
95     return dist[fin]*minflow;
96 }
原文地址:https://www.cnblogs.com/NaVi-Awson/p/7463215.html