洛谷 2055 BZOJ 1433 [ZJOI2009]假期的宿舍
【题解】
既然是一人对应一床,那么显然可以用二分图匹配来做。俩人认识的话,如果其中一个a是在校学生,另一个b不回家,b就可以向a的床连边(a,b当然也可以是同一个人)。
然后如果最大匹配数大于等于需要床的人数,就存在合法方案。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define N 100 5 #define rg register 6 using namespace std; 7 int T,n,cnt,tot,time,ans,last[N],v[N],from[N]; 8 bool sch[N],gh[N]; 9 struct edge{ 10 int to,pre; 11 }e[N*N]; 12 inline int read(){ 13 int k=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 15 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 16 return k*f; 17 } 18 int dfs(int x){ 19 for(rg int i=last[x],to;i;i=e[i].pre)if(v[to=e[i].to]!=time){ 20 v[to]=time; 21 if(!from[to]||dfs(from[to])){ 22 from[to]=x; 23 return 1; 24 } 25 } 26 return 0; 27 } 28 int main(){ 29 T=read(); 30 while(T--){ 31 memset(v,0,sizeof(v)); 32 memset(from,0,sizeof(from)); 33 memset(last,0,sizeof(last)); 34 ans=0; cnt=0; tot=0; time=0; 35 n=read(); 36 for(rg int i=1;i<=n;i++) sch[i]=read(); 37 for(rg int i=1;i<=n;i++){ 38 int x=read(); 39 if(sch[i]) if((gh[i]=x)==1) cnt++;else; 40 else gh[i]=0; 41 } 42 for(rg int i=1;i<=n;i++) 43 for(rg int j=1;j<=n;j++) if(read()==1||i==j){ 44 if(sch[i]&&!gh[j]) e[++tot]=(edge){i,last[j]},last[j]=tot; 45 if(sch[j]&&!gh[i]) e[++tot]=(edge){j,last[i]},last[i]=tot; 46 } 47 for(rg int i=1;i<=n;i++) if(!gh[i])time++,ans+=dfs(i); 48 puts(ans>=n-cnt?"^_^":"T_T"); 49 } 50 return 0; 51 }