题意
n个人,F种食物,D种饮料,每种食物,饮料的数量都已知,同时还知道哪个人喜欢吃/喝那些食物/饮料。最多多少人能够有吃有喝。
- 1<=n,F,D<=200。
- 输入:多组输入
- n,F,D
- F个整数表示食物i的数量
- D个整数表示饮料i的数量
- n*F矩阵,aij为'Y','D'分别表示第i个人喜欢/不喜欢食物j
- n*D矩阵,bij为'Y','D'分别表示第i个人喜欢/不喜欢饮料j
- 输出:一行一个整数表示人数
题解
网络流,建图难。s->食物->人_in->人_out->饮料->t,边权分别为食物数量,1,1,1,饮料数量。
代码
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
// #define int long long
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define pb push_back
using namespace std;
const int N = 1e3 + 10; // 2*n+F+D+2<1000
const int M = 2e5 + 10; //(n+F+D+n*F+n*D)*2<2e5
const int INF = 1e9 + 10;
struct Edge {
int v, w, next;
Edge(int v = 0, int w = 0, int next = 0) : v(v), w(w), next(next) {}
} e[M];
int head[N], cnt;
void add(int u, int v, int w) {
e[cnt] = Edge(v, w, head[u]), head[u] = cnt++;
e[cnt] = Edge(u, 0, head[v]), head[v] = cnt++;
}
int n, F, D, x;
int s, t;
char f, d;
int dep[N], now[N];
bool bfs() {
for (int i = 1; i <= t; i++) dep[i] = INF, now[i] = head[i];
queue<int> q;
q.push(s), dep[s] = 0;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = now[x]; ~i; i = e[i].next) {
int v = e[i].v;
if (dep[v] == INF && e[i].w > 0) {
dep[v] = dep[x] + 1;
if (v == t) return true;
q.push(v);
}
}
}
return false;
}
int dfs(int x, int flow) {
if (x == t) return flow;
int ans = 0;
for (int i = now[x]; ~i && flow; i = e[i].next) {
int v = e[i].v;
now[x] = i;
if (dep[x] + 1 == dep[v] && e[i].w > 0) {
int tmp = dfs(v, min(flow, e[i].w));
if (tmp == 0) dep[v] = INF;
e[i].w -= tmp;
e[i ^ 1].w += tmp;
ans += tmp;
flow -= tmp;
}
}
return ans;
}
int Dinic() {
int res = 0;
// cout << bfs() << endl;
while (bfs()) res += dfs(s, INF);
return res;
}
void build() {
s = 2 * n + F + D + 1, t = s + 1;
// people_in->people_out 。权值为1
//拆点思想
for (int i = 1; i <= n; i++) add(i, n + i, 1);
// s->food 。权值为该食物数量
for (int i = 1; i <= F; i++) read(x), add(s, 2 * n + i, x);
// drink->t 。权值为饮料数量
for (int i = 1; i <= D; i++) read(x), add(2 * n + F + i, t, x);
// food->people_in 。权值为1
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= F; j++) {
cin >> f;
if (f == 'Y') add(2 * n + j, i, 1);
}
}
// people_out->drink 。权值为1
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= D; j++) {
cin >> d;
if (d == 'Y') add(n + i, 2 * n + F + j, 1);
}
}
}
void init() { memset(head, -1, sizeof(head)), cnt = 0; }
signed main() {
while (scanf("%d%d%d", &n, &F, &D) != EOF) {
init();
build();
int maxflow = Dinic();
print(maxflow, '\n');
}
return 0;
}