洛谷 P1251 餐巾计划问题(线性规划网络优化)【费用流】

(题外话:心塞...大部分时间都在debug,拆点忘记加N,总边数算错,数据类型标错,字母写错......)

题目链接:https://www.luogu.org/problemnew/show/P1251

洛谷 P1251 餐巾计划问题

输入输出样例

输入样例#1:
3
1 7 5 
11 2 2 3 1
输出样例#1:
134

说明

N<=2000

ri<=10000000

p,f,s<=10000

时限4s

 

题解:拆点再跑费用流呗,第i天拆成Xi(脏的餐巾)和Yi(干净的餐巾)。对于每天情况,建图示例如下(解释详见代码注释):

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 4005;
 5 const int M = 24005;
 6 const ll INF = 1e18;
 7 const int INF2 = 1e9;
 8 struct Edge { int to,next,cap,flow,cost; }edge[M];
 9 int head[N],tol;
10 int pre[N];
11 ll dis[N];
12 bool vis[N];
13 int V;
14 void init(int n) {
15     V = n;
16     tol = 0;
17     memset(head,-1,sizeof(head));
18 }
19 void addedge(int u,int v,int cap,int cost) {
20     edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++;
21     edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;
22 }
23 bool spfa(int s,int t) {
24     queue<int>q;
25     for(int i = 0;i < V;i++) {
26         dis[i] = INF;
27         vis[i] = false;
28         pre[i] = -1;
29     }
30     dis[s] = 0;
31     vis[s] = true;
32     q.push(s);
33     while(!q.empty()) {
34         int u = q.front();
35         q.pop();
36         vis[u] = false;
37         for(int i = head[u]; i != -1;i = edge[i].next) {
38             int v = edge[i].to;
39             if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) {
40                 dis[v] = dis[u] + edge[i].cost;
41                 pre[v] = i;
42                 if(!vis[v]) {
43                     vis[v] = true;
44                     q.push(v);
45                 }
46             }
47         }
48     }
49     if(pre[t] == -1) return false;
50     else return true;
51 }
52 ll minCostMaxflow(int s,int t,ll &cost) {
53     ll flow = 0;
54     cost = 0;
55     while(spfa(s,t)) {
56         ll Min = INF;
57         for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) {
58             if(Min > edge[i].cap - edge[i].flow)
59                 Min = edge[i].cap - edge[i].flow;
60         }
61         for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) {
62             edge[i].flow += Min;
63             edge[i^1].flow -= Min;
64             cost += edge[i].cost * Min;
65         }
66         flow += Min;
67     }
68     return flow;
69 }
70 int main() {
71     int n, r, i, j, p, m, f, nn, s;
72     ll ans = 0;
73     scanf("%d", &n);
74     init(n*2+3);
75 
76     int S = n*2+1, T = n*2+2;
77 
78     for(i = 1; i <= n; ++i) {
79         scanf("%d", &r);//每天需要餐巾数
80         addedge(S, i, r, 0);
81         addedge(i+n, T, r, 0);
82     }
83     scanf("%d%d%d%d%d", &p, &m, &f, &nn, &s);
84     for(i = 1; i <= n; ++i) {
85         addedge(S, i+n, INF2, p);//购买新餐巾
86         if(i+m<=n) addedge(i, i+m+n, INF2, f);//快洗
87         if(i+nn<=n) addedge(i, i+nn+n, INF2, s);//慢洗
88         if(i!=n) addedge(i, i+1, INF2, 0);//留到第二天
89     }
90 
91     minCostMaxflow(S, T, ans);
92     printf("%lld\n", ans);
93     return 0;
94 }
View Code

 

posted @ 2018-05-14 21:56  GraceSkyer  阅读(454)  评论(0编辑  收藏  举报

~~~~~~ACM大牛语录,激励一下~~~~~~

为了世界的和平,为了女生的安全,我拼命做题,做题,做题!

用最短的时间,刷最多的题!

给我一滴泪,我就看到了你全部的海洋!

seize the hour, seize the day.

人生难免有无奈,幸福走远了,或是感叹幸福来迟了.其实我一直相信,无论手中的幸福是多么微不足道的感觉,我会把握住那每一分,每一秒,当幸福依旧像那百鸟般飞逝,终究无法掌握时,我会感谢它,曾经降临过!

A自己的题,让别人郁闷去吧

WA肠中过,AC心中留 TLE耳边过,AC特别牛

天然的悲苦和伤逝,过去有过,以后还会有

^*^一步一步往上爬^*^

AC就像练级,比赛就像PK. 练级不如PK好玩

其实,世上本没有ACM,AC的人多了,也便有了!

AC无止尽~ Seek you forever~

找呀找呀找水题,找到一个AC一个呀!

AC是检验程序的唯一标准。

真的猛士,敢于直面惨淡的人生,敢于正视淋漓的鲜血……