[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$成立,就不会读入了。