[bzoj1433][ZJOI2009]假期的宿舍——二分图

题目大意

传送门

题解

显然是二分图匹配。
用一些方法建图就好了。
要注意的是:
本题有多组数据!!!
初始化一定要注意!!!

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
const int inf = 0x3f3f3f;
int n;
// 1~n:学生
// n+1~n+k:床位
int isbed[maxn], insch[maxn];
int dist[maxn * 2], iter[maxn * 2];
struct edge {
  int to, cap, rev;
};
vector<edge> G[maxn];
void add_edge(int from, int to, int cap) {
  G[from].push_back((edge){to, cap, G[to].size()});
  G[to].push_back((edge){from, 0, G[from].size() - 1});
}
int cnt = 0;
void read() {
  scanf("%d", &n);
  memset(isbed, 0, sizeof(isbed));
  for (int i = 0; i <= 2 * n + 1; i++) {
    G[i].clear();
  }
  cnt = 0;
  for (int i = 1; i <= n; i++) {
    scanf("%d", &isbed[i]);
  }
  for (int i = 1; i <= n; i++) {
    scanf("%d", &insch[i]);
    insch[i] = insch[i] ^ 1;
  }
  for (int i = 1; i <= n; i++) {
    if (isbed[i])
      add_edge(i, i + n, 1);
    for (int j = 1; j <= n; j++) {
      int x;
      scanf("%d", &x);
      if (x && isbed[j]) {
        if (!(isbed[i]) || (isbed[i] && insch[i])) {
          add_edge(i, n + j, 1);
        }
      }
    }
    if (!(isbed[i]) || (isbed[i] && insch[i])) {
      cnt++;
      add_edge(0, i, 1);
    }
 
    if (isbed[i])
      add_edge(n + i, 2 * n + 1, 1);
  }
}
void bfs(int from) {
  memset(dist, -1, sizeof(dist));
  dist[from] = 0;
  queue<int> q;
  q.push(from);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = 0; i < G[u].size(); i++) {
      edge &e = G[u][i];
      if (dist[e.to] < 0 && e.cap > 0) {
        dist[e.to] = dist[u] + 1;
        q.push(e.to);
      }
    }
  }
}
int dfs(int from, int to, int f) {
  if (from == to)
    return f;
  for (int &i = iter[from]; i < G[from].size(); i++) {
    edge &e = G[from][i];
    if (e.cap > 0 && dist[e.to] > dist[from]) {
      int d = dfs(e.to, to, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}
int max_flow(int from, int to) {
  int flow = 0;
  for (;;) {
    bfs(from);
    if (dist[to] < 0)
      return flow;
    memset(iter, 0, sizeof(iter));
    int f;
    while ((f = dfs(from, to, inf) > 0))
      flow += f;
  }
}
int main() {
  //  freopen("input", "r", stdin);
  int T;
  scanf("%d", &T);
  while (T--) {
    cnt = 0;
    read();
    int ans = max_flow(0, 2 * n + 1);
    if (ans == cnt)
      printf("^_^\n");
    else
      printf("T_T\n");
  }
  return 0;
}

posted on 2017-02-15 18:57  蒟蒻konjac  阅读(161)  评论(0编辑  收藏  举报