题目传送门
有点恶心。
解法:
二分图匹配直接上。
如果你在校而且不回家,那么自己可以睡自己的床。
如果你认识的人在校,那么你可以睡他的床。
跑一遍最大匹配。。
话说题目描述好像有点问题吧。。
怎么A和B是在校学生B就可以睡A的床了。。
搞得我一开始以为在校的都互相认识。
WA无限。
代码实现:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node {int x,y,next;}a[110000];int len,last[11000];
void ins(int x,int y) {len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int t,chw[11000],match[11000];
bool findmuniu(int x) {
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
if(chw[y]!=t) {
chw[y]=t;if(match[y]==0||findmuniu(match[y])==true) {match[y]=x;return true;}
}
}return false;
}
int v[110],s[110];//v在校,s回家
int main() {
int T;scanf("%d",&T);
while(T--) {
int n;scanf("%d",&n);len=0;memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)scanf("%d",&v[i]);
for(int i=1;i<=n;i++)scanf("%d",&s[i]);
for(int i=1;i<=n;i++)if(v[i]==1&&s[i]==0)ins(i,i);
int cnt=0;for(int i=1;i<=n;i++)if(v[i]==0||(v[i]==1&&s[i]==0))cnt++;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) {
int x;scanf("%d",&x);
if(x==1&&(v[i]==0||(v[i]==1&&s[i]==0))&&v[j]==1)ins(i,j);
}
bool bk=true;memset(match,0,sizeof(match));memset(chw,0,sizeof(chw));t=0;int ans=0;
for(int i=1;i<=n;i++) {
t++;if(findmuniu(i)==true)ans++;
}
if(ans==cnt)printf("^_^\n");
else printf("T_T\n");
}
return 0;
}