POJ-3436 ACM Computer Factory 网络流
该题题义是这样的,有N台机器安排去组装电脑,每台电脑有P个零部件,一台可以出产的电脑必须要求每个部件都有。每台机器能够接受的本成品电脑不同,对于每个部件,输入数据给出了0(一定不能够在半成品上出现),1(一定要在上面出现),2(可以出现也可以不出现)。每台机器生产出来的半成品(或者成为了成品)的情况也有不同,对于每个部件0代表经过这个机器加工后,该号不见没有,相反,1代表有。
由于每台机器的处理能力有限,所以这里要将点拆成边,点内的边赋值为产能,其他边均赋值为无穷大。对部件没有要求的机器为源点,对部件都有要求的机器为汇点。考虑好机器与机器之间的传递关系,建图后直接计算最大流,最后在遍历两两点之间的flow。
代码如下:
#include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <queue> #define SP 0 #define T 2*N+1 #define INF 0x3fffffff #define CP(x) (N+(x)) #define MAXN 110 using namespace std; int P, N, cap[MAXN][MAXN], flow[MAXN][MAXN]; int c[MAXN], path[MAXN], MaxFlow; struct Node { int Q, S[15], D[15]; }e[55]; void init() { MaxFlow = 0; memset(cap, 0, sizeof (cap)); memset(flow, 0, sizeof (flow)); } bool Start(int x) { for (int i = 1; i <= P; ++i) { if (e[x].S[i] == 1) { return false; } } return true; } bool End(int x) { for (int i = 1; i <= P; ++i) { if (e[x].D[i] == 0) { return false; } } return true; } bool OK(int x, int y) { for (int i = 1; i <= P; ++i) { if (e[x].D[i] == 1 && (e[y].S[i] == 1 || e[y].S[i] == 2)) { continue; } else if (e[x].D[i] == 0 && (e[y].S[i] == 0 || e[y].S[i] == 2)) { continue; } else { return false; } } return true; } /* 3 4 15 0 0 0 0 1 0 10 0 0 0 0 1 1 30 0 1 2 1 1 1 3 0 2 1 1 1 1 */ void bfs() { int pos; bool finish = false; while (!finish) { memset(c, 0, sizeof (c)); queue<int>q; c[SP] = INF; q.push(SP); while (!q.empty()) { if (c[T]) { break; } pos = q.front(); q.pop(); for (int i = 1; i <= T; ++i) { if (!c[i] && cap[pos][i] > flow[pos][i]) { c[i] = min(c[pos], cap[pos][i]-flow[pos][i]); q.push(i); path[i] = pos; } } } if (c[T] == 0) { finish = true; } else { MaxFlow += c[T]; pos = T; while (pos != SP) { flow[path[pos]][pos] += c[T]; flow[pos][path[pos]] -= c[T]; pos = path[pos]; } } } } void print() { int M = 0; for (int i = 1; i <= N; ++i) { for (int j = 1; j <= N; ++j) { if (flow[CP(i)][j] > 0) { ++M; } } } printf("%d %d\n", MaxFlow, M); for (int i = 1; i <= N; ++i) { for (int j = 1; j <= N; ++j) { if (flow[CP(i)][j] > 0) { printf("%d %d %d\n", i, j, flow[CP(i)][j]); } } } } int main() { while (scanf("%d %d", &P, &N) == 2) { init(); for (int i = 1; i <= N; ++i) { scanf("%d", &e[i].Q); for (int j = 1; j <= P; ++j) { // 加工的条件 scanf("%d", &e[i].S[j]); } for (int j = 1; j <= P; ++j) { // 出产的特性 scanf("%d", &e[i].D[j]); } } for (int i = 1; i <= N; ++i) { if (Start(i)) { cap[SP][i] = INF; } if (End(i)) { cap[CP(i)][T] = INF; } cap[i][CP(i)] = e[i].Q; for (int j = 1; j <= N; ++j) { if (OK(i, j)) { cap[CP(i)][j] = INF; } } } bfs(); print(); } return 0; }