二分图匹配的题目。
但建边有一定难度,关系比较复杂。
首先要统计总共需要几张床。
在校且住校的会有一张床,不住校的有一张床。
然后对于在校且住校的与自己的床连边,不住校的与认识的住校的人连一条边。
跑一遍匈牙利就好了。
code:
/************************************************************** Problem: 1433 User: yekehe Language: C++ Result: Accepted Time:28 ms Memory:824 kb ****************************************************************/ #include <cstdio> #include <vector> #include <cstring> using namespace std; int read() { char c;while(c=getchar(),c<‘0‘||c>‘9‘); int x=c-‘0‘;while(c=getchar(),c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘; return x; } int T,N,o,cnt,ans; int k[55],w[55]; vector<int>a[55]; int vis[55],last[55],now; bool find(int x) { for(int i=0;i<a[x].size();i++){ int to=a[x][i]; if(vis[to]!=now){ vis[to]=now; if(!last[to] || find(last[to])){ last[to]=x; return true; } } } return false; } int main() { T=read(); register int i,j; while(T--){ ans=cnt=0; N=read(); memset(last,0,sizeof last); memset(a,0,sizeof a); for(i=1;i<=N;i++)k[i]=read(); for(i=1;i<=N;i++)w[i]=read(); for(i=1;i<=N;i++){ if(!k[i])cnt++; else { if(!w[i])cnt++,a[i].push_back(i); }//建边且统计创的数量 } for(i=1;i<=N;i++) for(j=1;j<=N;j++){ o=read(); if(!o)continue; if(k[j])a[i].push_back(j);//建边 } for(i=1;i<=N;i++) if(!k[i]||!w[i])now++,ans+=find(i);//二分图匹配 puts(ans==cnt?"^_^":"T_T"); } return 0; }