You, a part-time dining service worker in your college’s dining hall, are now confused with a new problem: serve as many people as possible.
The issue comes up as people in your college are more and more difficult to serve with meal: They eat only some certain kinds of food and drink, and with requirement unsatisfied, go away directly.
You have prepared F (1 <= F <= 200) kinds of food and D (1 <= D <= 200) kinds of drink. Each kind of food or drink has certain amount, that is, how many people could this food or drink serve. Besides, You know there’re N (1 <= N <= 200) people and you too can tell people’s personal preference for food and drink.
Back to your goal: to serve as many people as possible. So you must decide a plan where some people are served while requirements of the rest of them are unmet. You should notice that, when one’s requirement is unmet, he/she would just go away, refusing any service.
Input
There are several test cases.
For each test case, the first line contains three numbers: N,F,D, denoting the number of people, food, and drink.
The second line contains F integers, the ith number of which denotes amount of representative food.
The third line contains D integers, the ith number of which denotes amount of representative drink.
Following is N line, each consisting of a string of length F. ��e jth character in the ith one of these lines denotes whether people i would accept food j. “Y” for yes and “N” for no.
Following is N line, each consisting of a string of length D. ��e jth character in the ith one of these lines denotes whether people i would accept drink j. “Y” for yes and “N” for no.
Please process until EOF (End Of File).
Output
For each test case, please print a single line with one integer, the maximum number of people to be satisfied.
Sample Input
4 3 3
1 1 1
1 1 1
YYN
NYY
YNY
YNY
YNY
YYN
YYN
NNY
Sample Output
3
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int inf = 0x3fffffff;
template <int N, int M>
struct Isap
{
int top;
int d[N], pre[N], cur[N], gap[N];
struct Vertex {
int head;
} V[N];
struct Edge {
int v, next;
int c, f;
} E[M];
void init() {
memset(V, -1, sizeof(V));
top = 0;
}
void add_edge(int u, int v, int c) {
E[top].v = v;
E[top].c = c;
E[top].f = 0;
E[top].next = V[u].head;
V[u].head = top++;
}
void add(int u, int v, int c) {
add_edge(u, v, c);
add_edge(v, u, 0);
}
void set_d(int t) {
queue<int> Q;
memset(d, -1, sizeof(d));
memset(gap, 0, sizeof(gap));
d[t] = 0;
Q.push(t);
while (!Q.empty()) {
int v = Q.front(); Q.pop();
++gap[d[v]];
for (int i = V[v].head; ~i; i = E[i].next) {
int u = E[i].v;
if (d[u] == -1) {
d[u] = d[v] + 1;
Q.push(u);
}
}
}
}
int sap(int s, int t, int num) {
set_d(t);
int ans = 0, u = s;
int flow = inf;
memcpy(cur, V, sizeof(V));
while (d[s] < num) {
int &i = cur[u];
for (; ~i; i = E[i].next) {
int v = E[i].v;
if (E[i].c > E[i].f && d[u] == d[v] + 1) {
u = v;
pre[v] = i;
flow = min(flow, E[i].c - E[i].f);
if (u == t) {
while (u != s) {
int j = pre[u];
E[j].f += flow;
E[j ^ 1].f -= flow;
u = E[j ^ 1].v;
}
ans += flow;
flow = inf;
}
break;
}
}
if (i == -1) {
if (--gap[d[u]] == 0)
break;
int dmin = num - 1;
cur[u] = V[u].head;
for (int j = V[u].head; ~j; j = E[j].next)
if (E[j].c > E[j].f)
dmin = min(dmin, d[E[j].v]);
d[u] = dmin + 1;
++gap[d[u]];
if (u != s)
u = E[pre[u] ^ 1].v;
}
}
return ans;
}
};
Isap<100005, 200005> Sap;
int main()
{
int n, d, k;
while (cin >> n >> d >> k)
{
Sap.init();
int st = 6 * n, zt = 6 * n + 1;
for (int a = 1; a <= d; a++)
{
int w;
cin >> w;
Sap.add(st, a,w);
}
for (int a = 1; a <= k; a++)
{
int w;
cin >> w;
Sap.add(3*n+a, zt, w);
}
for (int a = 1; a <= n; a++)
{
Sap.add(n + a, 2 * n + a, 1);
}
for (int a = 1; a <= n; a++)
{
string q;
cin >> q;
for (int b = 0; b < q.size(); b++)
{
if (q[b] == 'Y')Sap.add(b + 1, n + a, 1);
}
}
for (int a = 1; a <= n; a++)
{
string q;
cin >> q;
for (int b = 0; b < q.size(); b++)
{
if (q[b] == 'Y')Sap.add(2*n+a, 3 * n + b+1, 1);
}
}
cout << Sap.sap(st, zt, 15 * n + 1)<