存一波匈牙利板子
check数组还是老老实实for一遍更新吧,回溯的时候更新容易出事
//:-)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int MAXN = 1000 + 50;
int n,c,x;
bool zx[MAXN],hj[MAXN];
bool need[MAXN];
struct edge{
int f,t;
}l[MAXN << 1];
int head[MAXN],next[MAXN << 1],tot;
void build(int f,int t){
l[++ tot] = (edge){f,t};
next[tot] = head[f];
head[f] = tot;
}
void init(int n){
tot = 0;
for(int i = 1;i <= n;i ++)
head[i] = -1;
}
int pd[MAXN];
bool check[MAXN];
int dfs(int u){
for(int i = head[u];i != -1;i = next[i]){
int t = l[i].t;
if((t <= n && !need[t]) || check[t])continue;
check[t] = true;
if(pd[t] == -1 || dfs(pd[t]) == 1){
pd[t] = u;
return 1;
}
}
return -1;
}
int T;
int main(){
scanf("%d",&T);
while(T --){
scanf("%d",&n);
memset(need,0,sizeof(need));
memset(zx,0,sizeof(zx));
memset(hj,0,sizeof(hj));
tot = 0;
memset(head,-1,sizeof(head));
for(int i = 1;i <= n;i ++){
scanf("%d",&zx[i]);
if(!zx[i])need[i] = true;
}
for(int i = 1;i <= n;i ++){
scanf("%d",&hj[i]);
if(zx[i] && !hj[i])need[i] = true;
}
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= n;j ++){
scanf("%d",&x);
if(x && zx[j]){
build(i,j + n);
}
}
if(zx[i] && !hj[i])build(i,i + n);
}
memset(pd,-1,sizeof(pd));
bool flag = false;
for(int i = 1;i <= n;i ++){
if(!need[i])continue;
if(pd[i] == -1){
memset(check,0,sizeof(check));
if(dfs(i) == -1){
flag = true;
break;
}
}
}
if(flag)printf("T_T\n");
else printf("^_^\n");
}
return 0;
}