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 }