代码改变世界

BZOJ1433 [ZJOI2009]假期的宿舍

2017-05-20 16:18  tlnshuju  阅读(185)  评论(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;
}