中文体面不再翻译,通过画图我们可以知道只是一道二分图匹配,那么如何进行匹配呢,我们要存一下,在校学生和外校学生的编号,然后走掉的人当床位,认识的人连边,用住校生和外校生与床位跑二分图匹配,做到这里,你大概能get到70%的分数,因为你没有考虑全面问题,还有一个必须考虑的条件是最大匹配数要等于需要匹配的人数,不然就有人无法睡觉233
代码
#include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int M=500; int t,n,m; int tot,cnt,ans; int a[M],b[M],c[M]; int map[M][M],mat[M],vis[M]; vector<int>v[M<<2]; int mid(int x) { for(int i=0;i<v[x].size();i++) { int go=v[x][i]; if (vis[go]) continue;; vis[go]=1; if(!mat[go]||mid(mat[go])) { mat[go]=x; return 1; } } return 0; } void clear() { memset(a,0,sizeof(a));memset(b,0,sizeof(b)); memset(c,0,sizeof(c));memset(mat,0,sizeof(mat)); memset(map,0,sizeof(map)); for (int i=1;i<=n;i++) v[i].clear(); return ; } void clean() { memset(vis,0,sizeof(vis)); return ; } void built() { for (int i=1;i<=cnt;i++) for (int k=1;k<=tot;k++) if (map[c[k]][b[i]]) v[b[i]].push_back(c[k]); } int main() { cin>>t; while (t--) { scanf("%d",&n);cnt=ans=tot=0;clear(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { scanf("%d",&m); if(a[i]) { if(m) c[++tot]=i; else b[++cnt]=c[++tot]=i; } else b[++cnt]=i; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>map[i][j]; for(int i=1;i<=n;i++) if(a[i]) map[i][i]=1; built(); for(int i=1;i<=cnt;clean(),i++) if(mid(b[i])) ans++; if(cnt>tot) ans=-1; if(ans==cnt) cout<<"^_^"<<endl; else cout<<"T_T"<<endl; } return 0; }