zoukankan      html  css  js  c++  java
  • [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("^_^
    ");
        else
          printf("T_T
    ");
      }
      return 0;
    }
    
  • 相关阅读:
    BZOJ1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
    BZOJ1031: [JSOI2007]字符加密Cipher
    关于后缀数组的实现
    BZOJ1692: [Usaco2007 Dec]队列变换
    BZOJ1725: [Usaco2006 Nov]Corn Fields牧场的安排
    POJ 2386 Lake Counting(搜索联通块)
    POJ 2386 Lake Counting(搜索联通块)
    Java演示设计模式中的写代码的代码
    Java演示设计模式中的写代码的代码
    源码映射
  • 原文地址:https://www.cnblogs.com/gengchen/p/6402818.html
Copyright © 2011-2022 走看看