洛谷 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 }