1. 程式人生 > >bzoj 1221: [HNOI2001] 軟件開發

bzoj 1221: [HNOI2001] 軟件開發

容量 size push 思路 from inf 每天 rst fine

思路:把每天拆乘兩個點Xi, Yi 兩堆點

建邊過程:

1、從S向每個Xi連一條容量為a[ i ],費用為0的有向邊。

2、從每個Yi向T連一條容量為a[ i ],費用為0的有向邊。

3、從S向每個Yi連一條容量為inf,費用為c1的有向邊。

4、從每個Xi向Xi + 1(i+1<=N)連一條容量為inf,費用為0的有向邊。

5、從每個Xi向Yi + p + 1(i + p + 1 <= N)連一條容量為inf,費用為f的有向邊。

6、從每個Xi向Yi + q + 1(i + q + 1<=N)連一條容量為inf,費用為s的有向邊。

註意:能少建邊就少見邊,我剛開始因為建了接近n^2的邊就T啦。。

費用流拉的別人的板子, 有空自己手敲一個。。。

  1 #include<bits/stdc++.h>
  2 #define LL long long
  3 #define fi first
  4 #define se second
  5 #define mk make_pair
  6 #define pii pair<int,int>
  7 #define piii pair<int,pair<int,int>>
  8 
  9 using namespace std;
 10 
 11 const int
N = 2000 + 7; 12 const int M = 5e5 + 7; 13 const int inf = 0x3f3f3f3f; 14 const LL INF = 0x3f3f3f3f3f3f3f3f; 15 const int mod = 1e9 + 7; 16 17 int n, p, q, c1, c2, c3, a[N]; 18 19 struct Edge 20 { 21 int from, to, cap, flow, cost, next; 22 }; 23 Edge edge[M]; 24 int head[N], edgenum;
25 int pre[N]; 26 int dist[N]; 27 bool vis[N]; 28 int source, sink; 29 void init() 30 { 31 edgenum = 0; 32 memset(head, -1, sizeof(head)); 33 } 34 void addEdge(int u, int v, int w, int c) 35 { 36 Edge E1 = {u, v, w, 0, c, head[u]}; 37 edge[edgenum] = E1; 38 head[u] = edgenum++; 39 Edge E2 = {v, u, 0, 0, -c, head[v]}; 40 edge[edgenum] = E2; 41 head[v] = edgenum++; 42 } 43 bool SPFA(int s, int t) 44 { 45 queue<int> Q; 46 memset(dist, INF, sizeof(dist)); 47 memset(vis, false, sizeof(vis)); 48 memset(pre, -1, sizeof(pre)); 49 dist[s] = 0; 50 vis[s] = true; 51 Q.push(s); 52 while(!Q.empty()) 53 { 54 int u = Q.front(); 55 Q.pop(); 56 vis[u] = false; 57 for(int i = head[u]; i != -1; i = edge[i].next) 58 { 59 Edge E = edge[i]; 60 if(dist[E.to] > dist[u] + E.cost && E.cap > E.flow) 61 { 62 dist[E.to] = dist[u] + E.cost; 63 pre[E.to] = i; 64 if(!vis[E.to]) 65 { 66 vis[E.to] = true; 67 Q.push(E.to); 68 } 69 } 70 } 71 } 72 return pre[t] != -1; 73 } 74 void MCMF(int s, int t, LL &cost, int &flow) 75 { 76 flow = 0; 77 cost = 0; 78 while(SPFA(s, t)) 79 { 80 int Min = INF; 81 for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 82 { 83 Edge E = edge[i]; 84 Min = min(Min, E.cap - E.flow); 85 } 86 //增廣 87 for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 88 { 89 edge[i].flow += Min; 90 edge[i^1].flow -= Min; 91 cost += edge[i].cost * Min; 92 } 93 flow += Min; 94 } 95 } 96 int main() { 97 init(); 98 scanf("%d%d%d%d%d%d", &n, &p, &q, &c1, &c2, &c3); 99 source = 0, sink = 2 * n + 1; 100 for(int i = 1; i <= n; i++) { 101 scanf("%d", &a[i]); 102 addEdge(source, i + n, a[i], c1); 103 addEdge(i + n, sink, a[i], 0); 104 addEdge(source, i, a[i], 0); 105 } 106 107 for(int i = 1; i <= n; i++) { 108 for(int j = i + p + 1; j < i + q + 1 && j <= n; j++) 109 addEdge(i, j + n, a[i], c2); 110 for(int j = i + q + 1; j <= n; j++) 111 addEdge(i, j + n, a[i], c3); 112 } 113 114 LL cost; 115 int flow; 116 MCMF(source, sink, cost, flow); 117 printf("%lld\n", cost); 118 return 0; 119 }

bzoj 1221: [HNOI2001] 軟件開發