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

Posted GraceSkyer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 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

 

以上是关于洛谷 P1251 餐巾计划问题(线性规划网络优化)费用流的主要内容,如果未能解决你的问题,请参考以下文章

P1251 餐巾计划问题

P1251 餐巾计划问题

P1251 餐巾计划问题

P1251 餐巾计划问题 (费用流)

AC日记——餐巾计划问题 洛谷 P1084

网络流24题餐巾计划问题(最小费用最大流)