BZOJ1433 [ZJOI2009]假期的宿舍
2017-05-20 16:18 tlnshuju 阅读(189) 评论(0) 编辑 收藏 举报题意:自行脑补
思路:网络流。建模显然,若满流则能够
代码:
#include <cstdio> #include <cstring> #include <cctype> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define INF 0x3f3f3f3f queue<int> q; struct Solver { int head[200], next[6010], end[6010], flow[6010], ind; int gap[200], d[200], stack[200], top, cur[200]; void reset() { ind = top = 0; memset(head, -1, sizeof(head)); } void addedge(int a, int b, int _flow) { int q = ind++; end[q] = b; next[q] = head[a]; head[a] = q; flow[q] = _flow; } void make(int a, int b, int _flow) { //printf("%d %d\n", a, b); addedge(a, b, _flow); addedge(b, a, 0); } void bfs(int T) { memset(d, -1, sizeof d); memset(gap, 0, sizeof gap); ++gap[d[T] = 0]; q.push(T); register int i, j; while(!q.empty()) { i = q.front(); q.pop(); for(j = head[i]; j != -1; j = next[j]) if (d[end[j]] == -1) ++gap[d[end[j]] = d[i] + 1], q.push(end[j]); } } int Maxflow(int S, int T) { bfs(T); memcpy(cur, head, sizeof cur); int u = S, res = 0, i, ins, Min; while(d[S] < T - S + 1) { if (u == T) { Min = INF; for(i = 0; i < top; ++i) if (flow[stack[i]] < Min) Min = flow[stack[i]], ins = i; for(i = 0; i < top; ++i) flow[stack[i]] -= Min, flow[stack[i] ^ 1] += Min; res += Min; u = end[stack[top = ins] ^ 1]; } if (u != T && !gap[d[u] - 1]) break; bool find = 0; for(int &j = cur[u]; j != -1; j = next[j]) if (flow[j] && d[end[j]] + 1 == d[u]) { find = 1; ins = j; break; } if (find) { cur[u] = ins; stack[top++] = ins; u = end[ins]; } else { Min = T - S + 1; for(int j = head[u]; j != -1; j = next[j]) { if (flow[j] && Min > d[end[j]]) { Min = d[end[j]]; cur[u] = j; } } if (!--gap[d[u]]) break; ++gap[d[u] = Min + 1]; if (u != S) u = end[stack[--top] ^ 1]; } } return res; } }G; int is_student[51], is_at_home[51], M[51][51]; int main() { int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); register int i, j; for(i = 1; i <= n; ++i) scanf("%d", &is_student[i]); for(i = 1; i <= n; ++i) scanf("%d", &is_at_home[i]); for(i = 1; i <= n; ++i) for(j = 1; j <= n; ++j) scanf("%d", &M[i][j]); for(i = 1; i <= n; ++i) M[i][i] = 1; G.reset(); int size = 0; for(i = 1; i <= n; ++i) if ((is_student[i] && !is_at_home[i]) || !is_student[i]) G.make(0, i, 1), ++size; for(i = 1; i <= n; ++i) if (is_student[i]) G.make(n + i, 2 * n + 1, 1); for(i = 1; i <= n; ++i) for(j = 1; j <= n; ++j) if (M[i][j]) G.make(i, n + j, 1); int res = G.Maxflow(0, 2 * n + 1); if (res == size) puts("^_^"); else puts("T_T"); } return 0; }