洛谷 P1251 餐巾計劃問題(線性規劃網絡優化)【費用流】
阿新 • • 發佈:2018-05-15
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];View Code13 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 }
洛谷 P1251 餐巾計劃問題(線性規劃網絡優化)【費用流】