满分做法:
把人向床连边进行二分图匹配即可。
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxm=5555;
int t,n,ans;
int school[maxm],home[maxm];
int pre[maxm],last[maxm],other[maxm],l;
int match[maxm];
bool vis[maxm];
void add(int x,int y)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
}
bool dfs(int x)
{
for(int p=last[x];p;p=pre[p])
{
int v=other[p];
if(vis[v]) continue;
vis[v]=1;
if(match[v]==-1||dfs(match[v]))
{
match[v]=x;
return 1;
}
}
return 0;
}
void dfs_xyl()
{
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++)
{
if(!school[i]||(school[i]&&!home[i]))
{
memset(vis,0,sizeof(vis));
if(dfs(i))
{
ans++;
}
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(last,0,sizeof(last));
int tot=0;
ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&school[i]);
for(int i=1;i<=n;i++)
{
scanf("%d",&home[i]);
if(school[i]&&!home[i])
add(i,i);
}
for(int i=1;i<=n;i++)
if(!school[i]||(school[i]&&!home[i])) tot++;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
if(x&&school[j])
add(i,j);
}
}
dfs_xyl();
if(ans!=tot)
printf("T_T
");
else printf("^_^
");
}
return 0;
}