BZOJ1433: [ZJOI2009]假期的宿舍
【传送门:BZOJ1433】
简要题意:
有n个人,给出一个关系图,表示人与人之间的认识关系,其中有若干个学生,每个学生在学校宿舍里都有一张床
有一次放假,有些学生要回家,有些不回家,留在宿舍,那些不回家的学生会把自己认识的人(不一定是学生)带到学校来住,每个人都只会睡在自己直接认识的人的床上,请问是否能够将所有人都有地方住(回家的学生回家了,就相当于有地方住了)
题解:
很显然,二分图匹配
将除了回家的学生的所有人,往这些人所认识所有学生连边(相当于向床连边),而不回家的学生也要向自己的床连边(怎么可能自己都不能睡自己的床)
然后跑二分图匹配就行了
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int v[51],b[51]; struct node { int x,y,next; }a[3100];int len,last[51]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int match[110]; int bk[110]; bool findmuniu(int x,int t) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(bk[y]!=t) { bk[y]=t; if(match[y]==0||findmuniu(match[y],t)==true) { match[y]=x; return true; } } } return false; } int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int x; scanf("%d",&x); if(x==1||i==j) { if(v[i]==1&&b[i]==1) continue; if(v[j]==1) ins(i,j+n); } } } memset(match,0,sizeof(match)); memset(bk,0,sizeof(bk)); bool bz=false; for(int i=1;i<=n;i++) { if(v[i]==0||(v[i]==1&&b[i]==0)) { if(findmuniu(i,i)==false) { printf("T_T\n");bz=true; break; } } } if(bz==false) printf("^_^\n"); } return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚