洛谷 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 }
View Code

 

posted @ 2018-04-22 22:01  Driver_Lao  阅读(213)  评论(0编辑  收藏  举报