题目连接
对于每个外校的、留校的本校生,都要匹配一个床,对于外校生,可以:
1.睡自己认识的人的床
对于每个留校本校生,可以:
1.睡自己的床
2.睡自己认识的人的床
由此建图,跑匈牙利算法,如果
最大匹配值==需要床的人数
则yes否则no
下面是ac代码:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e5+5;
int tot;
int he[1024], ne[1024], ver[1024];
int ho[1024], gg[1024], match[1024];
bool vis[1024];
void add(int x, int y)
{
ver[++tot] = y;
ne[tot] = he[x];
he[x] = tot;
}
void init()
{
memset(vis, 0, sizeof(vis));
memset(ne, 0, sizeof(ne));
memset(he, 0, sizeof(he));
tot = 1;
memset(match, 0, sizeof(match));
}
bool dfs(int x)
{
for (int i = he[x]; i; i = ne[i])
{
int y = ver[i];
if (!vis[y])
{
vis[y] = 1;
if (!match[y] || dfs(match[y]))
{
match[y] = x;
return 1;
}
}
}
return 0;
}
int main()
{
int t;
cin >> t;
while(t--)
{
init();
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &gg[i]);
}
for (int i = 1; i <= n; i++)
{
scanf("%d", &ho[i]);
if (!ho[i] && gg[i])
add(i, i);
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int te;
scanf("%d", &te);
if (te && gg[j])
add(i, j);
}
}
int _ans = 0;
for (int i = 1; i <= n; i++)
{
if (!gg[i] || (gg[i] && !ho[i]))
_ans++;
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (!gg[i] || (gg[i] && !ho[i]))
{
memset(vis, 0, sizeof(vis));
if (dfs(i)) ans++;
}
}
//cout <<_ans << " " << ans << endl;
if (_ans == ans) printf("^_^\n");
else printf("T_T\n");
}
return 0;
}