您的位置:首页 > 其它

bzoj 1391 [Ceoi2008]order - 最小割

2017-07-08 11:10 363 查看

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

Sample Output

50

HINT



  有点类似于最大权闭合子图。任务和源点连边,容量为获利,任务和完成它的工序所用机器连边,容量为租用费用,机器和汇点连边,容量为它的价格。答案是总获利 - 最大流。

  这些都还好。。最坑的是,我的模板在前几道题上正常运行,这道题用vectot炸掉了,一直鬼畜地Runtime Error,我也表示很绝望,换成数组才能Accepted。

Code

/**
* bzoj
* Problem#1391
* Accepted
* Time:4860ms
* Memory:46372k
*/
#include <iostream>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <stack>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
const signed int inf = (signed)((1u << 31) - 1);
const int eps = 1e-6;
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
#define max3(a, b, c) max(a, max(b, c))
#define min3(a, b, c) min(a, min(b, c))
template<typename T>
inline boolean readInteger(T& u){
char x;
int aFlag = 1;
while(!isdigit((x = getchar())) && x != '-' && x != -1);
if(x == -1) {
ungetc(x, stdin);
return false;
}
if(x == '-'){
x = getchar();
aFlag = -1;
}
for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
ungetc(x, stdin);
u *= aFlag;
return true;
}

typedef class Edge {
public:
int end;
int next;
int flow;
int cap;
Edge(int end = 0, int next = -1, int flow = 0, int cap = 0):end(end), next(next), flow(flow), cap(cap) {    }
}Edge;

typedef class MapManager {
public:
int ce;
Edge* edge;
int* h;

MapManager():ce(0), h(NULL) {        }
MapManager(int nodes, int limit):ce(0) {
h = new int[(const int)(nodes + 1)];
edge = new Edge[(const int)(limit + 1)];
memset(h, -1, sizeof(int) * (nodes + 1));
}

inline void addEdge(int from, int end, int flow, int cap) {
edge[ce] = (Edge(end, h[from], flow, cap));
h[from] = ce++;
}

inline void addDoubleEdge(int from, int end, int cap) {
addEdge(from, end, 0, cap);
addEdge(end, from, cap, cap);
}

Edge& operator [] (int pos) {
return edge[pos];
}
}MapManager;
#define m_begin(g, i) (g).h[(i)]
#define m_endpos -1

int n, m;
MapManager g;
int s, t;
int sum = 0;

inline void init() {
readInteger(n);
readInteger(m);
g = MapManager(n + m + 3, (n + 1) * (m + 1) * 2);
s = 0, t = n + m + 1;
for(int i = 1, a, b; i <= n; i++) {
readInteger(a);
readInteger(b);
g.addDoubleEdge(s, i, a);
sum += a;
for(int j = 1, c, d; j <= b; j++) {
readInteger(c);
readInteger(d);
g.addDoubleEdge(i, c + n, d);
}
}
for(int i = 1, a; i <= m; i++) {
readInteger(a);
g.addDoubleEdge(i + n, t, a);
}
}

int* dis;
boolean* vis;
queue<int> que;
inline boolean bfs() {
memset(vis, false, sizeof(boolean) * (t + 2));
que.push(s);
vis[s] = true;
dis[s] = 0;
while(!que.empty()) {
int e = que.front();
que.pop();
for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) {
if(g[i].cap == g[i].flow)    continue;
int eu = g[i].end;
if(vis[eu])    continue;
vis[eu] = true;
dis[eu] = dis[e] + 1;
que.push(eu);
}
}
return vis[t];
}

int *cur;
inline int blockedflow(int node, int minf) {
if((node == t) || (minf == 0))    return minf;
int f, flow = 0;
for(int& i = cur[node]; i != m_endpos; i = g[i].next) {
int& eu = g[i].end;
if(dis[eu] == (dis[node] + 1) && (f = blockedflow(eu, min(minf, g[i].cap - g[i].flow))) > 0) {
minf -= f;
flow += f;
g[i].flow += f;
g[i ^ 1].flow -= f;
if(minf == 0)    return flow;
}
}
return flow;
}

inline void init_dinic() {
vis = new boolean[(const int)(t + 3)];
dis = new int[(const int)(t + 3)];
cur = new int[(const int)(t + 3)];
}

inline int dinic() {
int maxflow = 0;
while(bfs()) {
for(int i = s; i <= t; i++)
cur[i] = m_begin(g, i);
maxflow += blockedflow(s, inf);
}
return maxflow;
}

inline void solve() {
printf("%d\n", sum - dinic());
}

int main() {
//    freopen("order.in", "r", stdin);
init();
init_dinic();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: