bzoj1433 [ZJOI2009]假期的宿舍

Description & Input

这里写图片描述

Output

这里写图片描述

Sample Input

1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0

Sample Output

ˆ_ˆ

Solution

匈牙利裸题,用来练手。人和床之间连边。注意连边条件,见代码。

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define N 51
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drp(i, a, b) for (int i = a; i >= b; i--)
#define fech(i, x) for (int i = 0; i < x.size(); i++)
#define ll long long

inline int read() {
    int x = 0, flag = 1; char ch = getchar();
    while (ch > '9' || ch < '0') { if (ch == '-') flag = -1; ch = getchar(); }
    while (ch <= '9' && ch >= '0') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * flag;
}
inline void write(int x) { if (x >= 10) write(x / 10); putchar(x % 10 + '0'); }

int n;
vector<int> g[N];
bool sch[N], bak[N];
int state[N], result[N], stt;

void init() {
    stt = 0;
    memset(sch, 0, sizeof sch);
    memset(bak, 0, sizeof bak);
    memset(state, 0, sizeof state);
    memset(result, 0, sizeof result);
    rep(i, 1, n) g[i].clear();
}

bool gou(int u) {
    fech(i, g[u]) {
        int v = g[u][i];
        if (state[v] == stt) continue;
        state[v] = stt;
        if (!result[v] || gou(result[v])) { result[v] = u; return true; }
    }
    return false;
}

int main() {
    int T = read();
    while (T--) {
        n = read(); int ans = 0, tot = n;
        init();
        rep(i, 1, n) sch[i] = read();
        rep(i, 1, n) {
            bak[i] = read();
            if (sch[i])
                if (bak[i]) tot--;
                else g[i].push_back(i);
            else bak[i] = 0;
        }
        rep(i, 1, n) rep(j, 1, n) if (read()) {
            if (sch[j] && !bak[i]) g[i].push_back(j);
            if (sch[i] && !bak[j]) g[j].push_back(i);
        }
        rep(i, 1, n) { stt++; if (gou(i)) ans++; }
        puts(ans == tot ? "^_^" : "T_T");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值