bzoj 1391 [Ceoi2008]order - 最小割
Description
有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。 现在给出这些参数,求最大利润
Input
第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,20000])
Output
最大利润
Sample Input
2 3
100 2
1 30
2 20
100 2
1 40
3 80
50
80
110
100 2
1 30
2 20
100 2
1 40
3 80
50
80
110
Sample Output
50
HINT
有点类似于最大权闭合子图。任务和源点连边,容量为获利,任务和完成它的工序所用机器连边,容量为租用费用,机器和汇点连边,容量为它的价格。答案是总获利 - 最大流。
这些都还好。。最坑的是,我的模板在前几道题上正常运行,这道题用vectot炸掉了,一直鬼畜地Runtime Error,我也表示很绝望,换成数组才能Accepted。
Code
1 /** 2 * bzoj 3 * Problem#1391 4 * Accepted 5 * Time:4860ms 6 * Memory:46372k 7 */ 8 #include <iostream> 9 #include <cstdio> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #include <cstring> 14 #include <cstdlib> 15 #include <fstream> 16 #include <sstream> 17 #include <algorithm> 18 #include <map> 19 #include <set> 20 #include <stack> 21 #include <queue> 22 #include <vector> 23 #include <stack> 24 #ifndef WIN32 25 #define Auto "%lld" 26 #else 27 #define Auto "%I64d" 28 #endif 29 using namespace std; 30 typedef bool boolean; 31 const signed int inf = (signed)((1u << 31) - 1); 32 const int eps = 1e-6; 33 #define smin(a, b) a = min(a, b) 34 #define smax(a, b) a = max(a, b) 35 #define max3(a, b, c) max(a, max(b, c)) 36 #define min3(a, b, c) min(a, min(b, c)) 37 template<typename T> 38 inline boolean readInteger(T& u){ 39 char x; 40 int aFlag = 1; 41 while(!isdigit((x = getchar())) && x != '-' && x != -1); 42 if(x == -1) { 43 ungetc(x, stdin); 44 return false; 45 } 46 if(x == '-'){ 47 x = getchar(); 48 aFlag = -1; 49 } 50 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 51 ungetc(x, stdin); 52 u *= aFlag; 53 return true; 54 } 55 56 typedef class Edge { 57 public: 58 int end; 59 int next; 60 int flow; 61 int cap; 62 Edge(int end = 0, int next = -1, int flow = 0, int cap = 0):end(end), next(next), flow(flow), cap(cap) { } 63 }Edge; 64 65 typedef class MapManager { 66 public: 67 int ce; 68 Edge* edge; 69 int* h; 70 71 MapManager():ce(0), h(NULL) { } 72 MapManager(int nodes, int limit):ce(0) { 73 h = new int[(const int)(nodes + 1)]; 74 edge = new Edge[(const int)(limit + 1)]; 75 memset(h, -1, sizeof(int) * (nodes + 1)); 76 } 77 78 inline void addEdge(int from, int end, int flow, int cap) { 79 edge[ce] = (Edge(end, h[from], flow, cap)); 80 h[from] = ce++; 81 } 82 83 inline void addDoubleEdge(int from, int end, int cap) { 84 addEdge(from, end, 0, cap); 85 addEdge(end, from, cap, cap); 86 } 87 88 Edge& operator [] (int pos) { 89 return edge[pos]; 90 } 91 }MapManager; 92 #define m_begin(g, i) (g).h[(i)] 93 #define m_endpos -1 94 95 int n, m; 96 MapManager g; 97 int s, t; 98 int sum = 0; 99 100 inline void init() { 101 readInteger(n); 102 readInteger(m); 103 g = MapManager(n + m + 3, (n + 1) * (m + 1) * 2); 104 s = 0, t = n + m + 1; 105 for(int i = 1, a, b; i <= n; i++) { 106 readInteger(a); 107 readInteger(b); 108 g.addDoubleEdge(s, i, a); 109 sum += a; 110 for(int j = 1, c, d; j <= b; j++) { 111 readInteger(c); 112 readInteger(d); 113 g.addDoubleEdge(i, c + n, d); 114 } 115 } 116 for(int i = 1, a; i <= m; i++) { 117 readInteger(a); 118 g.addDoubleEdge(i + n, t, a); 119 } 120 } 121 122 int* dis; 123 boolean* vis; 124 queue<int> que; 125 inline boolean bfs() { 126 memset(vis, false, sizeof(boolean) * (t + 2)); 127 que.push(s); 128 vis[s] = true; 129 dis[s] = 0; 130 while(!que.empty()) { 131 int e = que.front(); 132 que.pop(); 133 for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) { 134 if(g[i].cap == g[i].flow) continue; 135 int eu = g[i].end; 136 if(vis[eu]) continue; 137 vis[eu] = true; 138 dis[eu] = dis[e] + 1; 139 que.push(eu); 140 } 141 } 142 return vis[t]; 143 } 144 145 int *cur; 146 inline int blockedflow(int node, int minf) { 147 if((node == t) || (minf == 0)) return minf; 148 int f, flow = 0; 149 for(int& i = cur[node]; i != m_endpos; i = g[i].next) { 150 int& eu = g[i].end; 151 if(dis[eu] == (dis[node] + 1) && (f = blockedflow(eu, min(minf, g[i].cap - g[i].flow))) > 0) { 152 minf -= f; 153 flow += f; 154 g[i].flow += f; 155 g[i ^ 1].flow -= f; 156 if(minf == 0) return flow; 157 } 158 } 159 return flow; 160 } 161 162 inline void init_dinic() { 163 vis = new boolean[(const int)(t + 3)]; 164 dis = new int[(const int)(t + 3)]; 165 cur = new int[(const int)(t + 3)]; 166 } 167 168 inline int dinic() { 169 int maxflow = 0; 170 while(bfs()) { 171 for(int i = s; i <= t; i++) 172 cur[i] = m_begin(g, i); 173 maxflow += blockedflow(s, inf); 174 } 175 return maxflow; 176 } 177 178 inline void solve() { 179 printf("%d\n", sum - dinic()); 180 } 181 182 int main() { 183 // freopen("order.in", "r", stdin); 184 init(); 185 init_dinic(); 186 solve(); 187 return 0; 188 }