题意:自行脑补
思路:网络流,建模显然,若满流则可以
代码:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
queue<int> q;
struct Solver {
int head[200], next[6010], end[6010], flow[6010], ind;
int gap[200], d[200], stack[200], top, cur[200];
void reset() {
ind = top = 0;
memset(head, -1, sizeof(head));
}
void addedge(int a, int b, int _flow) {
int q = ind++;
end[q] = b;
next[q] = head[a];
head[a] = q;
flow[q] = _flow;
}
void make(int a, int b, int _flow) {
//printf("%d %d\n", a, b);
addedge(a, b, _flow);
addedge(b, a, 0);
}
void bfs(int T) {
memset(d, -1, sizeof d);
memset(gap, 0, sizeof gap);
++gap[d[T] = 0];
q.push(T);
register int i, j;
while(!q.empty()) {
i = q.front();
q.pop();
for(j = head[i]; j != -1; j = next[j])
if (d[end[j]] == -1)
++gap[d[end[j]] = d[i] + 1], q.push(end[j]);
}
}
int Maxflow(int S, int T) {
bfs(T);
memcpy(cur, head, sizeof cur);
int u = S, res = 0, i, ins, Min;
while(d[S] < T - S + 1) {
if (u == T) {
Min = INF;
for(i = 0; i < top; ++i)
if (flow[stack[i]] < Min)
Min = flow[stack[i]], ins = i;
for(i = 0; i < top; ++i)
flow[stack[i]] -= Min, flow[stack[i] ^ 1] += Min;
res += Min;
u = end[stack[top = ins] ^ 1];
}
if (u != T && !gap[d[u] - 1])
break;
bool find = 0;
for(int &j = cur[u]; j != -1; j = next[j])
if (flow[j] && d[end[j]] + 1 == d[u]) {
find = 1;
ins = j;
break;
}
if (find) {
cur[u] = ins;
stack[top++] = ins;
u = end[ins];
}
else {
Min = T - S + 1;
for(int j = head[u]; j != -1; j = next[j]) {
if (flow[j] && Min > d[end[j]]) {
Min = d[end[j]];
cur[u] = j;
}
}
if (!--gap[d[u]])
break;
++gap[d[u] = Min + 1];
if (u != S)
u = end[stack[--top] ^ 1];
}
}
return res;
}
}G;
int is_student[51], is_at_home[51], M[51][51];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
register int i, j;
for(i = 1; i <= n; ++i)
scanf("%d", &is_student[i]);
for(i = 1; i <= n; ++i)
scanf("%d", &is_at_home[i]);
for(i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j)
scanf("%d", &M[i][j]);
for(i = 1; i <= n; ++i)
M[i][i] = 1;
G.reset();
int size = 0;
for(i = 1; i <= n; ++i)
if ((is_student[i] && !is_at_home[i]) || !is_student[i])
G.make(0, i, 1), ++size;
for(i = 1; i <= n; ++i)
if (is_student[i])
G.make(n + i, 2 * n + 1, 1);
for(i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j)
if (M[i][j])
G.make(i, n + j, 1);
int res = G.Maxflow(0, 2 * n + 1);
if (res == size)
puts("^_^");
else
puts("T_T");
}
return 0;
}