POJ 3436 ACM Computer Factory 最大流
2016-07-26 09:49
525 查看
题意就是说,现在有一个电脑生产工厂,一个电脑可分为P个零件,工厂里共有N台机器
对于每台机器,Q,S1,S2,,,Sp,D1,D2,,,Dp,可以描述它,
其中Q为这台机器每个小时能生产的电脑数量,Si表示它对第i个零件的需求,0为这个零件必须为空,1为这个零件必须要有,2为有无皆可,Di表示它生产完成之后的第i个零件的状况,0为这个零件为空,1为有这个零件
然后问你每小时最大生成数量和具体的流程方式
最大流,建立一个超级源点,对于初始可以全部为空的,与超级源点连一条容量为INF的边,建一个超级汇点,对于生产之后全为1的,表示组装完成了,与超级汇点连一条容量为INF的边,对于每个点,拆成两个,进和出,中间连一条容量为它的生产速度的边,对于那些它的产出可以作为别人产入的,也连一条边,容量>=这两个机器的速度的最小值即可(因为在拆点那里对速度有了限制),然后从源点往汇点跑网络流就行
对于每台机器,Q,S1,S2,,,Sp,D1,D2,,,Dp,可以描述它,
其中Q为这台机器每个小时能生产的电脑数量,Si表示它对第i个零件的需求,0为这个零件必须为空,1为这个零件必须要有,2为有无皆可,Di表示它生产完成之后的第i个零件的状况,0为这个零件为空,1为有这个零件
然后问你每小时最大生成数量和具体的流程方式
最大流,建立一个超级源点,对于初始可以全部为空的,与超级源点连一条容量为INF的边,建一个超级汇点,对于生产之后全为1的,表示组装完成了,与超级汇点连一条容量为INF的边,对于每个点,拆成两个,进和出,中间连一条容量为它的生产速度的边,对于那些它的产出可以作为别人产入的,也连一条边,容量>=这两个机器的速度的最小值即可(因为在拆点那里对速度有了限制),然后从源点往汇点跑网络流就行
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <string> #include <fstream> #include <list> #include <stack> #include <queue> #include <deque> #include <algorithm> #include <map> #include <set> #include <vector> using namespace std; //ISAP+bfs 初始化+栈优化 #define maxn 120//点数的最大值 #define maxm 14400//边数的最大值 #define INF 0x3f3f3f3f struct Edge { int to, next, cap, flow; }edge[maxm];//注意是maxm int tol; int head[maxn]; int gap[maxn], dep[maxn], cur[maxn]; void init() { tol = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int w, int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[maxn]; void BFS(int start, int end) { memset(dep, -1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while (front != rear) { int u = Q[front++]; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[maxn]; //N是总顶点数,编号[0,N-1] int sap(int start, int end, int N) { BFS(start, end); memcpy(cur, head, sizeof(head)); int top = 0; int u = start; int ans = 0; while (dep[start] < N) { if (u == end) { int Min = INF; int inser; for (int i = 0; i < top; i++) if (Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for (int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i] ^ 1].flow -= Min; } ans += Min; top = inser; u = edge[S[top] ^ 1].to; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]) { flag = true; cur[u] = i; break; } } if (flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if (u != start)u = edge[S[--top] ^ 1].to; } return ans; } int P, N; int in[55][15], out[55][15]; int velocity[55]; int oper[3605][3]; int main() { //freopen("input.txt", "r", stdin); while (scanf("%d%d", &P, &N) != EOF) { init(); memset(in, 0, sizeof(int) * 55 * 15); memset(out, 0, sizeof(int) * 55 * 15); memset(velocity, 0, sizeof(int) * 55); memset(oper, 0, sizeof(int) * 3605 * 3); for (int i = 1; i <= N; ++i) { scanf("%d", &velocity[i]); for (int j = 0; j < P; ++j) scanf("%d", &in[i][j]); for (int j = 0; j < P; ++j) scanf("%d", &out[i][j]); } for (int i = 1; i <= N; ++i) { addedge(i * 2 - 1, i * 2, velocity[i]); bool flag = true; for (int j = 0; j < P; ++j) { if (in[i][j] == 1) { flag = false; break; } } if (flag) { addedge(0, i * 2 - 1, INF); } flag = true; for (int j = 0; j < P; ++j) { if (out[i][j] == 0) { flag = false; break; } } if (flag) { addedge(i * 2, 2 * N + 1, INF); } for (int j = 1; j <= N; ++j) { if (j == i) continue; flag = true; for (int k = 0; k < P; ++k) { if (out[i][k] + in[j][k] == 1)//不匹配 { flag = false; break; } } if (flag) { addedge(2 * i, 2 * j - 1, min(velocity[i], velocity[j])); } } } int ans = sap(0, 2 * N + 1, 2 * N + 2); int sum = 0; for (int i = 1; i <= N; ++i) { for (int j = head[i * 2]; j != -1; j = edge[j].next) { if (edge[j].to == 2 * N + 1 || edge[j].to == 0 || edge[j].flow <= 0 || edge[j].flow >= INF) continue; oper[sum][0] = i; oper[sum][1] = (edge[j].to + 1) / 2; oper[sum++][2] = edge[j].flow; } } printf("%d %d\n", ans, sum); for (int i = 0; i < sum; ++i) { printf("%d %d %d\n", oper[i][0], oper[i][1], oper[i][2]); } } //while (1); return 0; }
相关文章推荐
- Android中如何实现版本更新
- virtualbox安装ubuntu共享文件夹无访问权限问题解决方法
- 客户端早会——今日一享(如何给一个类动态扩展新功能?)
- MySQL常用基本SQL语句总结
- 响应式框架pure--来自雅虎
- 面试题(一)—Java基础(上)
- easelJS - Cache_vday
- 线程同步与死锁
- Cron表达式
- 原根
- UI网络笔记(二):UI网络之Post同步和异步的密文请求
- Android App监听自身卸载,反馈统计
- Java中的多态
- HDU1010
- Linux中强大的top命令
- 货车运输
- Linux下Tomcat开机自动启动
- Flink - DataStream
- Hdu5737-Differencia(有序表线段树)
- 5)函数极限与连续函数