把人和床分开考虑,题目说每个人只能睡和自己直接认识的人的床,就是一种边的关系,但是并不是人与人,实际上人与人之间连边是很难处理的,但是如果把人和床连边,就是一张二分图,左右两边分别是不同的东西,然后求一下最大匹配就好了
没思路的时候换换角度,看能不能搞出什么“新东西”来
注意多组数据不超时的情况下能用memset尽量用,有时候感觉某个数组可以不清空但实际上是需要清空的
还有注意连边的时候没那么简单。。。看注释吧
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 210;
int n,m,match[MAXN],ans,edge_tot,tot,outnum,last[MAXN],vis[MAXN],gra[MAXN][MAXN],house[MAXN];
int sch[MAXN],t,bad[MAXN];
struct Edge{
int u,v,to;
Edge(){}
Edge(int u, int v, int to) : u(u), v(v), to(to) {}
}e[10010];
inline void add(int u, int v) {
e[++edge_tot] = Edge(u, v, last[u]);
last[u] = edge_tot;
}
bool dfs(int x) {
for(int i=last[x]; i; i=e[i].to) {
int v = e[i].v;
if(vis[v]) continue;
vis[v] = 1;
if(!match[v] || dfs(match[v])) {
match[v] = x;
return true;
}
}
return false;
}
int main() {
scanf("%d", &t);
while(t--) {
ans = 0, edge_tot = 0, outnum = 0;
memset(match, 0, sizeof(match));
memset(last, 0, sizeof(last));
memset(house, 0, sizeof(house));
memset(sch, 0, sizeof(sch));
scanf("%d", &n);
for(int i=1; i<=n; i++) {
scanf("%d", &sch[i]);
}
for(int i=1; i<=n; i++) {
int temp_sca = 0;
if(sch[i] == 1) scanf("%d", &house[i]);
else scanf("%d", &temp_sca), outnum++;
if(!house[i] && sch[i]) {//和自己的床连边,首先i得有床,其次得不回家
outnum++;
add(i, i+n);
add(i+n, i);
}
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
scanf("%d", &gra[i][j]);
if(gra[i][j] && sch[j] && house[i] == 0) {
add(i, j+n);//i这个人和j的床位连边,需要i不是回家的人并且j是有床的(j不一定必须回家)
add(j+n, i);
}
}
}
for(int i=1; i<=n; i++) {
if(!house[i]) {
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
}
if(ans == outnum) {
printf("^_^\n");
} else printf("T_T\n");
}
return 0;
}