1. 程式人生 > >洛谷 P1251 餐巾計劃問題(線性規劃網絡優化)【費用流】

洛谷 P1251 餐巾計劃問題(線性規劃網絡優化)【費用流】

spfa n) blank ini 網絡優化 DC for sca .org

(題外話:心塞...大部分時間都在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 餐巾計劃問題(線性規劃網絡優化)【費用流】