一道最大流的题目,题意大概是:某某人有m个猪圈,有n个顾客,顾客要买猪,每个顾客手头有若干个猪圈的钥匙,每个顾客只能买他有钥匙的那个猪圈的猪,顾客买猪有先后顺序,问能卖出最多多少猪。
主要是建图,当当前顾客能打开的猪圈在以后某个顾客也能打开时,在当前顾客和那个顾客之间连一条边,权值为无穷大。
/*
* File: pku1149.cpp
* Author: chenjiang
*
* Created on 2010年3月24日, 下午12:31
*/
#include <stdlib.h>
#include <queue>
#include <iostream>
using namespace std;
#define inf 2147483
#define Max_V 120
int mapmap[Max_V][Max_V], min_flow[Max_V], flow[Max_V][Max_V];
int n, m, V, source, sink, pig[1005], house[1005], pre[Max_V];
int link[1005][105];
int MIN(int a, int b) {
return a < b ? a : b;
}
int max_flow() {
int i, j, k;
memset(flow, 0, sizeof (flow));
int ans = 0;
while (1) {
queue<int> Q;
Q.push(source);
memset(pre, -1, sizeof (pre));
min_flow[source] = inf;
pre[source] = -2;
while (!Q.empty()) {
int temp = Q.front();
Q.pop();
for (i = 0; i <= sink; i++) {
if (pre[i] == -1 && flow[temp][i] < mapmap[temp][i]) {
Q.push(i);
pre[i] = temp;
min_flow[i] = MIN(min_flow[temp], (mapmap[temp][i] - flow[temp][i]));
}
}
if (pre[sink] != -1) {
k = sink;
while (pre[k] >= 0) {
flow[pre[k]][k] += min_flow[sink];
flow[k][pre[k]] = -flow[pre[k]][k];
k = pre[k];
}
break;
}
}
if (pre[sink] == -1)return ans;
else ans += min_flow[sink];
}
}
/*
*
*/
int main(int argc, char** argv) {
int i, j, k, A, B, t;
while (cin >> m >> n) {
memset(mapmap, 0, sizeof (mapmap));
memset(link, 0, sizeof (link));
source = 0;
sink = n + 1;
for (i = 1; i <= m; i++) {
cin >> pig[i]; //每个猪圈里猪的个数
}
for (i = 1; i <= n; i++) {//顾客
cin >> A; //输入当前顾客能打开的猪圈个数
for (j = 1; j <= A; j++) {//能打开的猪圈
cin >> house[j]; //输入当前顾客能打开的猪圈
bool flag = 0;
for (t = 1; t < i; t++) {//
if (link[house[j]][t] != 0) {//如果house[j]与t有一条边
mapmap[t][i] = inf; //顾客t和i有一条无限大的边
flag = 1;
}
}
if (flag == 0) {//如果house[j]和i前面的顾客都没有联系,则与i连接
mapmap[source][i]+=pig[house[j]];
link[house[j]][i]=pig[house[j]];
}
}
cin >> B;
for (j = 1; j <= A; j++) {
mapmap[i][sink] = B;//顾客和汇点连接
}
}/*
for (i = 0; i <= sink; i++) {
for (j = i + 1; j <= sink; j++) {
printf("mapmap[%d][%d]=%d/n", i, j, mapmap[i][j]);
}
}
system("pause");*/
cout << max_flow() << endl;
}
return (EXIT_SUCCESS);
}