[ZJOI2009]假期的宿舍

原题传送门

这道题分析下就会发现是一个二分图匹配。将在校(包括来校访友)和床单构成图,判断最大匹配数是否为总在校人数即可。

这里用的是$KM$算法。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define re register
 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
 7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
 8 #define maxx(a, b) a = max(a, b);
 9 #define minn(a, b) a = min(a, b);
10 #define LL long long
11 #define inf (1 << 30)
12 
13 inline int read() {
14     int w = 0, f = 1; char c = getchar();
15     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
16     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
17     return w * f;
18 }
19 
20 const int maxn = 50 + 5;
21 
22 int e[maxn << 1][maxn << 1], n, T, a[maxn];
23 
24 int lk[maxn << 1], v[maxn << 1];
25 
26 bool find(int u) {
27     rep(x, n+1, n << 1) 
28         if (e[u][x] && !v[x]) {
29             v[x] = 1;
30             if (!lk[x] || find(lk[x])) {
31                 lk[x] = u;
32                 return true;
33             }
34         }
35     return false;
36 }
37 
38 int main() {
39     T = read();
40 
41     rep(kase, 1, T) {
42         memset(e, 0, sizeof(e));
43         memset(lk, 0, sizeof(lk));
44         memset(a, 0, sizeof(a));
45         n = read();
46         int ans = 0;
47         rep(i, 1, n) a[i] = read();
48         rep(i, 1, n)
49             a[i+n] = read() == 0 || a[i] == 0, ans += a[i+n] ? 1 : 0;
50         rep(i, 1, n)
51             rep(j, 1, n)
52                 if ((read() || i == j) && a[i] && a[j+n]) e[i][j+n] = 1;
53         rep(i, 1, n) {
54             memset(v, 0, sizeof(v));
55             find(i);
56         }
57         rep(i, n+1, n<<1) if (lk[i]) ans--;
58         if (ans <= 0) printf("^_^\n"); else printf("T_T\n");
59     }
60 
61     return 0;
62 }

这道题我提交了好几次,总是$WA$。经过仔细的调试(瞪眼观察法),发现第$49$行中:

$a[i+n] = read() == 0 || a[i] == 0;$

写的是

$a[i+n] = a[i] == 0 || read() == 0;$

$||$运算是短路运算,如果$a[i]=0$成立,就不会读入了。

posted @ 2019-01-28 01:04  AC-Evil  阅读(127)  评论(0编辑  收藏  举报