Problem p02107 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using ll = long long;
// #define int ll
#define FOR(i, a, b) for (int i = (a); i < int(b); ++i)
#define RFOR(i, a, b) for (int i = (b)-1; i >= int(a); --i)
#define rep(i, n) FOR(i, 0, n)
#define rep1(i, n) FOR(i, 1, int(n) + 1)
#define rrep(i, n) RFOR(i, 0, n)
#define rrep1(i, n) RFOR(i, 1, int(n) + 1)
#define all(c) begin(c), end(c)
// const int MOD = 1000000007;

template <typename T>
void __print__(std::ostream &os, const char *, const char *tail, const T &fst) {
  os << fst << tail;
}
template <typename Fst, typename... Rst>
void __print__(std::ostream &os, const char *del, const char *tail,
               const Fst &fst, const Rst &...rst) {
  os << fst << del;
  __print__(os, del, tail, rst...);
}

#ifdef LOCAL
#define dump(...)                                                              \\
  do {                                                                         \\
    std::ostringstream os;                                                     \\
    os << __LINE__ << ":\\t" << #__VA_ARGS__ << " = ";                          \\
    __print__(os, ", ", "\\n", __VA_ARGS__);                                    \\
    std::cerr << os.str();                                                     \\
  } while (0)
#else
#define dump(...)
#endif

template <typename Fst, typename... Rst>
void println(const Fst &fst, const Rst &...rst) {
  __print__(std::cout, "\\n", "\\n", fst, rst...);
}
template <typename Fst, typename... Rst>
void print(const Fst &fst, const Rst &...rst) {
  __print__(std::cout, " ", "\\n", fst, rst...);
}

template <typename iter> void println_(iter bgn, iter end) {
  while (bgn != end)
    println(*bgn++);
}

template <typename iter> void print_(iter bgn, iter end) {
  while (bgn != end) {
    std::cout << *bgn++;
    std::cout << (bgn == end ? "\\n" : " ");
  }
}

int _ = (std::cout.precision(10), std::cout.setf(std::ios::fixed),
         std::cin.tie(0), std::ios::sync_with_stdio(0), 0);

template <typename T> std::vector<T> ndarray(int n, T v) {
  return std::vector<T>(n, v);
}
template <typename... Args> auto ndarray(int n, Args... args) {
  auto val = ndarray(args...);
  return std::vector<decltype(val)>(n, move(val));
}

template <typename T> bool umax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> bool umin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

using namespace std;
using flow_type = int;

struct dinic {
  struct Edge {
    int s, d;
    flow_type c, f;
    int r;
  };
  int n, s, t;
  std::vector<std::vector<Edge>> g;
  std::vector<int> level, prog, que;

  dinic(int n_ = 0) : n(n_), g(n_) {}

  flow_type maximum_flow(int s_, int t_) {
    s = s_;
    t = t_;
    que.resize(n);
    flow_type res = 0;
    while (levelize()) {
      prog.assign(n, 0);
      res += augment(s, std::numeric_limits<flow_type>::max());
    }
    return res;
  }

  void add_edge(int u, int v, flow_type c) {
    if (u == v || c == 0)
      return;
    g[u].push_back({u, v, c, 0, (int)g[v].size()});
    g[v].push_back({v, u, c, c, (int)g[u].size() - 1});
  }

  bool levelize() {
    int fst = 0, lst = 0;
    que[lst++] = s;
    level.assign(n, -1);
    level[s] = 0;
    while (fst != lst) {
      int v = que[fst++];
      if (v == t)
        break;
      for (auto &e : g[v]) {
        if (level[e.d] == -1 && residue(e) != 0) {
          level[e.d] = level[v] + 1;
          que[lst++] = e.d;
        }
      }
    }
    return level[t] != -1;
  }

  flow_type augment(int v, flow_type lim) {
    flow_type res = 0;
    if (v == t)
      return lim;
    for (int &i = prog[v]; i < (int)g[v].size(); ++i) {
      if (lim == 0)
        break;
      auto &e = g[v][i];
      if (level[v] < level[e.d] && residue(e) != 0) {
        flow_type aug = augment(e.d, std::min(lim, residue(e)));
        if (aug == 0)
          continue;
        e.f += aug;
        reverse(e).f -= aug;
        res += aug;
        lim -= aug;
      }
    }
    return res;
  }

  flow_type residue(const Edge &e) { return e.c - e.f; }

  Edge &reverse(const Edge &e) { return g[e.d][e.r]; }
};

template <class F> struct maximum_flow_lower_bound {
  F flow;
  int S, T;
  flow_type sum_lb;

  maximum_flow_lower_bound() {}

  maximum_flow_lower_bound(int n) : flow(n + 2), S(n), T(n + 1), sum_lb(0) {}

  void add_edge(int u, int v, int lb, int ub) {
    assert(0 <= lb);
    assert(lb <= ub);
    if (u == v || ub == 0)
      return;
    flow.add_edge(u, v, ub - lb);
    // Three lines below should have no effect if lb == 0.
    flow.add_edge(S, v, lb);
    flow.add_edge(u, T, lb);
    sum_lb += lb;
  }

  flow_type maximum_flow(int s, int t) {
    int S = flow.n - 2, T = flow.n - 1;
    flow_type f = 0;
    flow.maximum_flow(S, T);
    f += flow.maximum_flow(s, T);
    flow.maximum_flow(S, t);
    f += flow.maximum_flow(s, t);
    for (auto &e : flow.g[S]) {
      if (flow.residue(e) > 0) {
        return -1;
      }
    }
    for (auto &e : flow.g[T]) {
      if (flow.residue(flow.reverse(e)) > 0) {
        return -1;
      }
    }
    // flow_type g = 0;
    // for (auto &e : flow.g[s]) {
    //     if (e.d != T) {
    //         f += e.f;
    //     }
    // }
    // dump(g);
    return f;
  }
};

int n, m;
int c[110][110];

// ????¬???° [lb, ub], ?????§????????? x ??§?????§??????????????°
int match(int lb, int ub, int x) {
  maximum_flow_lower_bound<dinic> dn(n + m + 2);
  rep(i, n) rep(j, m) {
    if (c[i][j] <= x) {
      dn.add_edge(i, j + n, 0, 1);
    }
  }
  int S = n + m;
  int T = S + 1;
  rep(i, n) { dn.add_edge(S, i, lb, ub); }
  rep(i, m) { dn.add_edge(i + n, T, 1, 1); }
  return dn.maximum_flow(S, T);
}

int main() {
  {
    maximum_flow_lower_bound<dinic> dn(3);
    dn.add_edge(0, 1, 1, 2);
    dn.add_edge(1, 2, 2, 3);
    assert(dn.maximum_flow(0, 2) == 2);
  }

  while (cin >> n >> m) {
    rep(i, n) rep(j, m) cin >> c[i][j];
    // assert(match(1, 1, INF) == n);
    // assert(match(0, 1, INF) == n);

    int minx = 0, maxx = 1e9 + 1;
    while (minx + 1 < maxx) {
      int x = (minx + maxx) / 2;
      int f = match(m / n, (m + n - 1) / n, x);
      if (f == m) {
        maxx = x;
      } else {
        minx = x;
      }
    }

    println((m + n - 1) / n - m / n, maxx);
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using ll = long long;
// #define int ll
#define FOR(i, a, b) for (int i = (a); i < int(b); ++i)
#define RFOR(i, a, b) for (int i = (b)-1; i >= int(a); --i)
#define rep(i, n) FOR(i, 0, n)
#define rep1(i, n) FOR(i, 1, int(n) + 1)
#define rrep(i, n) RFOR(i, 0, n)
#define rrep1(i, n) RFOR(i, 1, int(n) + 1)
#define all(c) begin(c), end(c)
// const int MOD = 1000000007;

template <typename T>
void __print__(std::ostream &os, const char *, const char *tail, const T &fst) {
  os << fst << tail;
}
template <typename Fst, typename... Rst>
void __print__(std::ostream &os, const char *del, const char *tail,
               const Fst &fst, const Rst &...rst) {
  os << fst << del;
  __print__(os, del, tail, rst...);
}

#ifdef LOCAL
#define dump(...)                                                              \\
  do {                                                                         \\
    std::ostringstream os;                                                     \\
    os << __LINE__ << ":\\t" << #__VA_ARGS__ << " = ";                          \\
    __print__(os, ", ", "\\n", __VA_ARGS__);                                    \\
    std::cerr << os.str();                                                     \\
  } while (0)
#else
#define dump(...)
#endif

template <typename Fst, typename... Rst>
void println(const Fst &fst, const Rst &...rst) {
  __print__(std::cout, "\\n", "\\n", fst, rst...);
}
template <typename Fst, typename... Rst>
void print(const Fst &fst, const Rst &...rst) {
  __print__(std::cout, " ", "\\n", fst, rst...);
}

template <typename iter> void println_(iter bgn, iter end) {
  while (bgn != end)
    println(*bgn++);
}

template <typename iter> void print_(iter bgn, iter end) {
  while (bgn != end) {
    std::cout << *bgn++;
    std::cout << (bgn == end ? "\\n" : " ");
  }
}

int _ = (std::cout.precision(10), std::cout.setf(std::ios::fixed),
         std::cin.tie(0), std::ios::sync_with_stdio(0), 0);

template <typename T> std::vector<T> ndarray(int n, T v) {
  return std::vector<T>(n, v);
}
template <typename... Args> auto ndarray(int n, Args... args) {
  auto val = ndarray(args...);
  return std::vector<decltype(val)>(n, move(val));
}

template <typename T> bool umax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> bool umin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

using namespace std;
using flow_type = int;

struct dinic {
  struct Edge {
    int s, d;
    flow_type c, f;
    int r;
  };
  int n, s, t;
  std::vector<std::vector<Edge>> g;
  std::vector<int> level, prog, que;

  dinic(int n_ = 0) : n(n_), g(n_) {}

  flow_type maximum_flow(int s_, int t_) {
    s = s_;
    t = t_;
    que.resize(n);
    flow_type res = 0;
    while (levelize()) {
      prog.assign(n, 0);
      res += augment(s, std::numeric_limits<flow_type>::max());
    }
    return res;
  }

  void add_edge(int u, int v, flow_type c) {
    if (u == v || c == 0)
      return;
    g[u].push_back({u, v, c, 0, (int)g[v].size()});
    g[v].push_back({v, u, c, c, (int)g[u].size() - 1});
  }

  bool levelize() {
    int fst = 0, lst = 0;
    que[lst++] = s;
    level.assign(n, -1);
    level[s] = 0;
    while (fst != lst) {
      int v = que[fst++];
      if (v == t)
        break;
      for (auto &e : g[v]) {
        if (level[e.d] == -1 && residue(e) != 0) {
          level[e.d] = level[v] + 1;
          que[lst++] = e.d;
        }
      }
    }
    return level[t] != -1;
  }

  flow_type augment(int v, flow_type lim) {
    flow_type res = 0;
    if (v == t)
      return lim;
    for (int &i = prog[v]; i < (int)g[v].size(); ++i) {
      if (lim == 0)
        break;
      auto &e = g[v][i];
      if (level[v] < level[e.d] && residue(e) != 0) {
        flow_type aug = augment(e.d, std::min(lim, residue(e)));
        if (aug == 0)
          continue;
        e.f += aug;
        reverse(e).f -= aug;
        res += aug;
        lim -= aug;
      }
    }
    return res;
  }

  flow_type residue(const Edge &e) { return e.c - e.f; }

  Edge &reverse(const Edge &e) { return g[e.d][e.r]; }
};

template <class F> struct maximum_flow_lower_bound {
  F flow;
  int S, T;
  flow_type sum_lb;

  maximum_flow_lower_bound() {}

  maximum_flow_lower_bound(int n) : flow(n + 2), S(n), T(n + 1), sum_lb(0) {}

  void add_edge(int u, int v, int lb, int ub) {
    assert(0 <= lb);
    assert(lb <= ub);
    if (u == v || ub == 0)
      return;
    flow.add_edge(u, v, ub - lb);
    // Three lines below should have no effect if lb == 0.
    flow.add_edge(S, v, lb);
    flow.add_edge(u, T, lb);
    sum_lb += lb;
  }

  flow_type maximum_flow(int s, int t) {
    int S = flow.n - 2, T = flow.n - 1;
    flow_type f = 0;
    flow.maximum_flow(S, T);
    f += flow.maximum_flow(s, T);
    flow.maximum_flow(S, t);
    f += flow.maximum_flow(s, t);
    for (auto &e : flow.g[S]) {
      if (flow.residue(e) > 0) {
        return -1;
      }
    }
    for (auto &e : flow.g[T]) {
      if (flow.residue(flow.reverse(e)) > 0) {
        return -1;
      }
    }
    // flow_type g = 0;
    // for (auto &e : flow.g[s]) {
    //     if (e.d != T) {
    //         f += e.f;
    //     }
    // }
    // dump(g);
    return f;
  }
};

int n, m;
int c[110][110];

// ????¬???° [lb, ub], ?????§????????? x ??§?????§??????????????°
int match(int lb, int ub, int x) {
  maximum_flow_lower_bound<dinic> dn(n + m + 2);
  rep(i, n) rep(j, m) {
    if (c[i][j] <= x) {
      dn.add_edge(i, j + n, 0, 1);
    }
  }
  int S = n + m;
  int T = S + 1;
  rep(i, n) { dn.add_edge(S, i, lb, ub); }
  rep(i, m) { dn.add_edge(i + n, T, 1, 1); }
  return dn.maximum_flow(S, T);
}

const int INF = 1e9;

int main() {
  {
    maximum_flow_lower_bound<dinic> dn(3);
    dn.add_edge(0, 1, 1, 2);
    dn.add_edge(1, 2, 2, 3);
    assert(dn.maximum_flow(0, 2) == 2);
  }

  while (cin >> n >> m) {
    rep(i, n) rep(j, m) cin >> c[i][j];
    // assert(match(1, 1, INF) == n);
    // assert(match(0, 1, INF) == n);

    int minw = INF;
    for (int i = 0; i <= m; ++i) {
      for (int j = i; j <= m; ++j) {
        int f = match(i, j, INF);
        // dump(i, j, f);
        if (f == m) {
          minw = min(minw, j - i);
        }
      }
    }
    dump(minw);

    int minx = 0, maxx = 1e9 + 1;
    while (minx + 1 < maxx) {
      int x = (minx + maxx) / 2;
      bool ok = false;
      for (int i = 0, j = minw; j <= m; ++i, ++j) {
        int f = match(i, j, x);
        dump(i, j, x, f);
        if (f == m) {
          ok = true;
          i = j = m + 1;
        }
      }
      if (ok) {
        maxx = x;
      } else {
        minx = x;
      }
    }

    println(minw, maxx);
  }
}