对于学生和床,可以看成是二分图,让尽可能多的学生能睡到床上,可以看成二分图的最大匹配
对于本校学生,自己可以睡自己的床和认识的人的床,我们连一条边
对于外校学生,可以睡认识的人的床,我们连一条边
然后跑一边匈牙利算法就AC啦
*********************************************
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#define MAXV 55
#define MAXE 55*55*2
using namespace std;
int V,E;
int bf[MAXV];
int check[MAXV];
int first[MAXV],nextt[MAXE],to[MAXE];
int sch[MAXV],home[MAXV];
int found(int x){
for(int e=first[x];e;e=nextt[e]){
int y=to[e];
if(!check[y]){
check[y]=1;
if(!bf[y]||found(bf[y])){
bf[y]=x;
return 1;
}
}
}
return 0;
}
void add(int x,int y){
E++;
nextt[E]=first[x];
first[x]=E;
to[E]=y;
}
int solve(){
memset(bf,0,sizeof(bf));
memset(check,0,sizeof(check));
memset(first,0,sizeof(first));
memset(nextt,0,sizeof(nextt));
memset(to,0,sizeof(to));
memset(sch,0,sizeof(sch));
memset(home,0,sizeof(home));
scanf("%d",&V);
E=0;
for(int i=1;i<=V;i++){
scanf("%d",&sch[i]);
}
for(int i=1;i<=V;i++){
scanf("%d",&home[i]);
}
for(int i=1;i<=V;i++){
for(int j=1;j<=V;j++){
int temp;
scanf("%d",&temp);
if((temp||i==j)&&sch[j]){
add(i,j);
}
}
}
for(int i=1;i<=V;i++){
if((sch[i]&&!home[i])||!sch[i]){
memset(check,0,sizeof(check));
if(!found(i)){
return 0;
}
}
}
return 1;
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
int T;
scanf("%d",&T);
while(T--){
if(solve()){
printf("^_^\n");
}
else{
printf("T_T\n");
}
}
return 0;
}