由于一个人对应一张床,所以考虑到二分图匹配
对于不离校的住校生,直接将自己与自己的床建边
离校的学生当然不用建边
对于非住校生,那就和他有人际关系的人的床连边
最后统计最大匹配即可
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int t,n,x,cnt,vis[maxn],mat[maxn],s[maxn],h[maxn],head[maxn];
struct edge
{
int to,nxt;
}G[maxn];
void add(int x,int y)
{
G[++cnt].nxt=head[x]; G[cnt].to=y; head[x]=cnt;
}
bool dfs(int u)
{
for(int i=head[u];i;i=G[i].nxt)
{
int to=G[i].to;
if(!vis[to])
{
vis[to]=1;
if(!mat[to] || dfs(mat[to]))
{
mat[to]=u;
return true;
}
}
}
return false;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(head,0,sizeof(head)); cnt=0; for(int i=1;i<=n;i++) scanf("%d",&s[i]);
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
for(int i=1;i<=n;i++)
if(s[i]==1 && !h[i]) add(i,i);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&x);
if(x&& s[j]) add(i,j);
}
memset(mat,0,sizeof(mat));
int ans=0,tot=0;
for(int i=1;i<=n;i++)
{
if((s[i]&& !h[i] ) || !s[i])
{
tot++;
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
}
if(ans==tot)
printf("^_^\n");
else printf("T_T\n");
}
return 0;
}