这题面和软件有个。。。毛关系啊!!!
建图什么的还是挺好想的。。。懒得写了,copy from AutSky_JadeK:"
把每天分为二分图两个集合中的顶点Xi,Yi,建立附加源S汇T。
1、从S向每个Xi连一条容量为ri,费用为0的有向边。
2、从每个Yi向T连一条容量为ri,费用为0的有向边。
3、从S向每个Yi连一条容量为无穷大,费用为p的有向边。
4、从每个Xi向Xi+1(i+1<=N)连一条容量为无穷大,费用为0的有向边。
5、从每个Xi向Yi+m+1(i+m+1<=N)连一条容量为无穷大,费用为f的有向边。
6、从每个Xi向Yi+n+1(i+n+1<=N)连一条容量为无穷大,费用为s的有向边。
求网络最小费用最大流,费用流值就是要求的最小总花费。"
补充:S、T分别表示毛巾来源和公司
1 /************************************************************** 2 Problem: 1221 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1736 ms 7 Memory:1780 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 2005; 15 const int M = N * 30; 16 const int inf = (int) 1e9; 17 18 struct edges { 19 int next, to, f, cost; 20 edges() {} 21 edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {} 22 } e[M]; 23 24 int n, S, T; 25 int first[N], tot = 1; 26 int d[N], g[N], q[N]; 27 bool v[N]; 28 29 inline void Add_Edges(int x, int y, int f, int c) { 30 e[++tot] = edges(first[x], y, f, c), first[x] = tot; 31 e[++tot] = edges(first[y], x, 0, -c), first[y] = tot; 32 } 33 34 inline int calc() { 35 int flow = inf, x; 36 for (x = g[T]; x; x = g[e[x ^ 1].to]) 37 flow = min(flow, e[x].f); 38 for (x = g[T]; x; x = g[e[x ^ 1].to]) 39 e[x].f -= flow, e[x ^ 1].f += flow; 40 return flow; 41 } 42 43 bool spfa() { 44 int x, y, l, r; 45 for (x = 1; x <= T; ++x) 46 d[x] = inf; 47 d[S] = 0, v[S] = 1, q[0] = S; 48 for(l = r = 0; l != (r + 1) % N; ++l %= N) { 49 for (x = first[q[l]]; x; x = e[x].next) 50 if (d[q[l]] + e[x].cost < d[y = e[x].to] && e[x].f) { 51 d[y] = d[q[l]] + e[x].cost, g[y] = x; 52 if (!v[y]) 53 q[++r %= N] = y, v[y] = 1; 54 } 55 v[q[l]] = 0; 56 } 57 return d[T] != inf; 58 } 59 60 inline int work() { 61 int res = 0; 62 while (spfa()) 63 res += calc() * d[T]; 64 return res; 65 } 66 67 int main() { 68 int i, a, b,f, fa, fb, x; 69 scanf("%d%d%d%d%d%d", &n, &a, &b, &f, &fa, &fb); 70 S = n * 2 + 1, T = S + 1; 71 for (i = 1; i <= n; ++i) { 72 if (i + 1 <= n) Add_Edges(i, i + 1, inf, 0); 73 if (i + a + 1 <= n) Add_Edges(i, n + i + a + 1, inf, fa); 74 if (i + b + 1 <= n) Add_Edges(i, n + i + b + 1, inf, fb); 75 Add_Edges(S, n + i, inf, f); 76 scanf("%d", &x); 77 Add_Edges(S, i, x, 0); 78 Add_Edges(n + i, T, x, 0); 79 } 80 printf("%d ", work()); 81 }
(p.s. 那个、、、rank 1的0ms是怎么做到的←_←)