該題題義是這樣的,有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 110using 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 415 0 0 0 0 1 010 0 0 0 0 1 130 0 1 2 1 1 13 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;}