zoukankan      html  css  js  c++  java
  • 【最大流/二分图匹配】【网络流24题】【P3254】 圆桌问题

    Description

    假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。

    会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。

    为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。

    对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。输出方案。

    Limitation

    (1~leq~m~leq~50,~1~leq~n~leq~270)

    Solution

    好裸的最大流啊……网络流24题怎么有这么水的题……

    源点向单位连边,容量为人数

    单位向餐桌连边,容量为 (1),代表一个餐桌最多做一个该单位的人

    餐桌向汇点连边,容量为餐桌大小,代表最多做多少人

    跑个最大流就好了……

    输出方案的话,对每个单位,枚举看向哪个餐桌的流量为 (1) 即可

    貌似还可以神仙贪心?

    Code

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #ifdef ONLINE_JUDGE
    #define freopen(a, b, c)
    #endif
    
    typedef long long int ll;
    
    namespace IPT {
      const int L = 1000000;
      char buf[L], *front=buf, *end=buf;
      char GetChar() {
        if (front == end) {
          end = buf + fread(front = buf, 1, L, stdin);
          if (front == end) return -1;
        }
        return *(front++);
      }
    }
    
    template <typename T>
    inline void qr(T &x) {
      char ch = IPT::GetChar(), lst = ' ';
      while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
      while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
      if (lst == '-') x = -x;
    }
    
    namespace OPT {
      char buf[120];
    }
    
    template <typename T>
    inline void qw(T x, const char aft, const bool pt) {
      if (x < 0) {x = -x, putchar('-');}
      int top=0;
      do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
      while (top) putchar(OPT::buf[top--]);
      if (pt) putchar(aft);
    }
    
    const int maxn = 400;
    const int INF = 0x3f3f3f3f;
    
    struct Edge {
      int u, v, flow;
      Edge *nxt, *bk;
    
      Edge(const int _u, const int _v, const int _flow, Edge* &h) 
          : u(_u), v(_v), flow(_flow), nxt(h) {
        h = this;
      }
    };
    Edge *hd[maxn], *fir[maxn];
    inline void cont(const int _u, const int _v, const int _flow) {
      auto u = new Edge(_u, _v, _flow, hd[_u]), v = new Edge(_v, _u, 0, hd[_v]);
      (u->bk = v)->bk = u;
    }
    
    int n, m, s, t, ans;
    int MU[maxn], CU[maxn], lp[maxn], rp[maxn], dist[maxn];
    std::queue<int>Q;
    
    bool bfs();
    int dfs(const int u, int canag);
    void printans();
    
    int main() {
      freopen("1.in", "r", stdin);
      qr(n); qr(m);
      for (int i = 1; i <= n; ++i) {
        qr(MU[i]);
        lp[i] = ++t;
      }
      for (int i = 1; i <= m; ++i) {
        qr(CU[i]); rp[i] = ++t;
      }
      s = ++t; ++t;
      for (int i = 1; i <= n; ++i) {
        cont(s, lp[i], MU[i]);
      }
      for (int i = 1; i <= m; ++i) {
        cont(rp[i], t, CU[i]);
      }
      for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
          cont(lp[i], rp[j], 1);
        }
      }
      while (bfs()) {
        for (int i = 1; i <= t; ++i) fir[i] = hd[i];
        dfs(s, INF);
      }
      printans();
      return 0;
    }
    
    void printans() {
      ans = 1;
      for (auto e = hd[s]; e; e = e->nxt) {
        ans &= (e->flow == 0);
      }
      qw(ans, '
    ', true);
      if (ans) {
        for (int u = 1; u <= n; ++u) {
          for (auto e = hd[u]; e; e = e->nxt) if (e->flow == 0) {
            qw(e->v - n, ' ', true);
          }
          putchar('
    ');
        }
      }
    }
    
    bool bfs() {
      memset(dist, 0, sizeof dist);
      dist[s] = 1; Q.push(s);
      while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (auto e = hd[u]; e; e = e->nxt) if (e->flow > 0) {
          int v = e->v;
          if (dist[v] == 0) {
            dist[v] = dist[u] + 1;
            Q.push(v);
          }
        }
      }
      return dist[t];
    }
    
    int dfs(const int u, int canag) {
      if ((u == t) || (!canag)) return canag;
      int _f = 0;
      for (auto &e = fir[u]; e; e = e->nxt) if (e->flow > 0) {
        int v = e->v;
        if (dist[v] == (dist[u] + 1)) {
          int f = dfs(v, std::min(e->flow, canag));
          e->flow -= f; e->bk->flow += f; _f += f;
          if (!(canag -= f)) {
            break;
          }
        }
      }
      return _f;
    }
    
  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10561622.html
Copyright © 2011-2022 走看看