BZOJ1433 [ZJOI2009]假期的宿舍

Description

Input

Output

Sample Input

1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0

Sample Output

ˆ ˆ

HINT

对于30% 的数据满足1 ≤ n ≤ 12。
对于100% 的数据满足1 ≤ n ≤ 50,1 ≤ T ≤ 20。

 
正解:二分图匹配(匈牙利算法)
解题报告:
  直接跑匈牙利算法。注意连边的关系,只有当i需要床位而且j可能提供床位时才连边,而且i不回家时,向自己连边。
  注意最大匹配的时候vis数组不能记i本身,因为可以匹配自己。细节问题。
 
 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 51;
21 int n,ans,cnt,a[MAXN][MAXN],b[MAXN],c[MAXN],match[MAXN];
22 bool vis[MAXN];
23 
24 inline int getint()
25 {
26        int w=0,q=0;
27        char c=getchar();
28        while((c<'0' || c>'9') && c!='-') c=getchar();
29        if (c=='-')  q=1, c=getchar();
30        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
31        return q ? -w : w;
32 }
33 
34 inline bool dfs(int x){
35     //不能加这一步!!!可能会匹配自己!!!
36     //vis[x]=1
37     for(int i=1;i<=n;i++) {
38     if(a[x][i] && !vis[i]) {
39         vis[i]=1;
40         if(!match[i] || dfs(match[i])) {
41         match[i]=x;
42         // match[x]=i;不能标记两边
43         return true;
44         }
45     }
46     }
47     return false;
48 }
49 
50 inline void work(){
51     int T=getint();
52     while(T--) {
53     memset(a,0,sizeof(a));memset(match,0,sizeof(match));
54     n=getint(); ans=0; cnt=0;
55     for(int i=1;i<=n;i++) b[i]=getint(); for(int i=1;i<=n;i++) c[i]=getint();
56     for(int i=1;i<=n;i++) if(!b[i] || (b[i]&&!c[i])) cnt++;//统计需要床位的人数
57     int x;
58     for(int i=1;i<=n;i++) {
59         for(int j=1;j<=n;j++) {
60         x=getint(); 
61         if(x && ((b[i] && !c[i]) || !b[i] ) &&b[j]) //表示i需要床位,而且i、j认识,并且j可能提供床位
62             a[i][j]=1;
63         }
64         if(b[i] && !c[i]) a[i][i]=1;//留校的在校生肯定可以睡自己床上
65     }
66     for(int i=1;i<=n;i++) {
67         memset(vis,0,sizeof(vis));
68         if(dfs(i)) ans++;       
69     }        
70     if(ans==cnt) printf("^_^\n");
71     else printf("T_T\n");
72     }
73 }
74 
75 int main()
76 {
77   work();
78   return 0;
79 }

 

posted @ 2016-08-13 12:26  ljh_2000  阅读(282)  评论(0编辑  收藏  举报