cychester

BZOJ1433 [ZJOI2009]假期的宿舍 - 二分图匹配

题解

一道裸的二分图匹配,稍微有一点细节需要注意, 但是非常裸= =

本校并且住校的向自己的床和 自己认识的并且本校的人的床连边

离校的不需要向外连边

不是本校的就和自己认识的 并且是本校的人的床连边 

最后跑匈牙利就可以了

代码

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rd read()
 5 #define rep(i,a,b) for(int i = (a); i <= (b); ++i)
 6 #define per(i,a,b) for(int i = (a); i >= (b); --i)
 7 using namespace std;
 8 
 9 const int N = 100;
10 
11 int used[N], pre[N], n, T, head[N], tot, ans;
12 bool in[N], back[N];
13 
14 struct edge{
15     int nxt, to;
16 }e[N << 2];
17 
18 int read() {
19     int X = 0, p = 1; char c = getchar();
20     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
21     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
22     return X * p;
23 }
24 
25 void add(int u, int v) {
26     e[++tot].to = v;
27     e[tot].nxt = head[u];
28     head[u] = tot;
29 }
30 
31 int fd(int u) {
32     for(int i = head[u]; i; i = e[i].nxt) {
33         int nt = e[i].to;
34         if(used[nt]) continue;
35         used[nt] = 1;
36         if(!pre[nt] || fd(pre[nt])) {
37             pre[nt] = u;
38             return 1;
39         }
40     }
41     return 0;
42 }
43 
44 int main()
45 {
46     T = rd;
47     for(; T; T--) {
48         n = rd;
49         memset(head,0,sizeof(head));
50         memset(pre, 0, sizeof(pre));
51         ans = tot = 0;
52         for(int i = 1; i <= n; ++i) {
53             int x = rd;
54             in[i] = x ? true : false;
55         }
56         for(int i = 1; i <= n; ++i) {
57             int x = rd;
58             back[i] = x ? true : false;
59             if(in[i] && !back[i]) ans++;
60             if(!in[i]) ans++;
61         }
62         for(int i = 1; i <= n; ++i)
63             for(int j = 1; j <= n; ++j) {
64                 int x = rd;
65                 if(i == j && in[i]) {
66                     add(i, i);
67                     continue;
68                 }
69                 if(!x) continue;
70                 if(in[j]) add(i, j);
71                 if(in[i]) add(j, i);
72             }
73         for(int i = 1; i <= n; ++i) if((in[i] && !back[i]) || !in[i]) {
74             memset(used, 0, sizeof(used));
75             if(!fd(i)) break;
76             else ans--;
77         }
78         if(ans) printf("T_T\n");
79         else printf("^_^\n");
80     }
81 }
View Code

 

posted on 2018-08-20 14:04  cychester  阅读(132)  评论(0编辑  收藏  举报

导航