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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_map>
#include <vector>

using namespace std;
typedef long long ll;

/*
????????????????????¬??????MinCostFlow????????????????????????????????????
?????????????????°?????????????????????Primal-dual??? ??????????????????
????????????????????????2,3???????????§???????????????????????¨
*/

/*
RadixHeap
??´??°?????¢dijkstra??§???????????¨?????????
priority_queue???????????????
*/

int nlz(int x) {
  if (x == 0)
    return 32;
  return __builtin_clz(x);
}
struct RadixHeap {
  typedef pair<int, int> P;
  vector<P> v[32];
  int mi, sz;
  RadixHeap() { mi = sz = 0; }
  void first(int x, int p) {
    sz = 1;
    mi = x;
    v[0].push_back(P(x, p));
  }
  void push(int x, int p) {
    if (!sz) {
      first(x, p);
      return;
    }
    sz++;
    v[32 - nlz(x ^ mi)].push_back(P(x, p));
  }
  void push(P p) { push(p.first, p.second); }
  void renew() {
    assert(!v[0].size());
    int i = 1;
    while (!v[i].size())
      i++;
    mi = v[i][0].first;
    for (P &d : v[i]) {
      mi = min(mi, d.first);
    }
    for (P &p : v[i]) {
      v[32 - nlz(mi ^ p.first)].push_back(p);
    }
    v[i].clear();
  }
  P top() {
    if (!v[0].size()) {
      renew();
    }
    assert(v[0].size());
    return v[0].back();
  }
  P pop() {
    sz--;
    if (!v[0].size()) {
      renew();
    }
    P r = v[0].back();
    v[0].pop_back();
    return r;
  }
  int size() { return sz; }
  bool empty() { return sz == 0; }
};

const int INF = 1 << 28;
template <int V> struct MinCostFlow {
  typedef int T;
  typedef pair<T, int> P;
  struct Edge {
    int to, rev;
    int cap;
    T cost;
  };
  vector<Edge> g[V];
  T h[V], dist[V];
  int pv[V], pe[V];
  void init() {
    for (int i = 0; i < V; i++) {
      g[i].clear();
    }
  }
  /// ????????????
  void add(int from, int to, int cap, T cost) {
    g[from].push_back(Edge{to, (int)g[to].size(), cap, cost});
    g[to].push_back(Edge{from, (int)g[from].size() - 1, 0, -cost});
  }
  /**
   * ????°??????¨???????¨??????????
   *
   * bell?????¢?????????????????????????????¨????????´????????????????????°????????§????§£??????????????¨?????¨???
   *
   * Params:
   *   s = ?§????
   *   t = ??????
   *   f = ?????????
   *   bell = ?????????????????????????????¨??????????????????
   */
  T exec(int s, int t, int f, bool bell = false) {
    T res = 0;
    fill_n(h, V, 0);
    while (f > 0) {
      fill_n(dist, V, INF);
      dist[s] = 0;
      if (bell) {
        bell = false;
        bool update;
        do {
          update = false;
          for (int v = 0; v < V; v++) {
            if (dist[v] == INF)
              continue;
            for (int i = 0; i < (int)g[v].size(); i++) {
              Edge &e = g[v][i];
              if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
                dist[e.to] = dist[v] + e.cost;
                pv[e.to] = v;
                pe[e.to] = i;
                update = true;
              }
            }
          }
        } while (update);
      } else {
        RadixHeap que;
        //                priority_queue<P, vector<P>, greater<P>> que;
        que.push(P(0, s));
        while (!que.empty()) {
          P p = que.top();
          que.pop();
          int v = p.second;
          if (dist[v] < p.first)
            continue;
          for (int i = 0; i < (int)g[v].size(); i++) {
            Edge &e = g[v][i];
            if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
              dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
              pv[e.to] = v;
              pe[e.to] = i;
              que.push(P(dist[e.to], e.to));
            }
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      for (int v = 0; v < V; v++) {
        h[v] += dist[v];
      }

      T d = f;
      for (int v = t; v != s; v = pv[v]) {
        d = min(d, g[pv[v]][pe[v]].cap);
      }
      f -= d;
      res += d * h[t];
      for (int v = t; v != s; v = pv[v]) {
        Edge &e = g[pv[v]][pe[v]];
        e.cap -= d;
        g[v][e.rev].cap += d;
      }
    }
    return res;
  }
};

const int MN = 110;
const int MM = 6;
int n, m, b, k;
int ax[MN], ay[MN];
int bx[MM], by[MM], c[MM], f[MM];

MinCostFlow<130> mf;

int calc(int md) {
  //    printf("startcalc:%d\\n", md);
  mf.init();
  /**
   * 0..MN p
   * MN..MN+MM k
   * 120:s 121:t
   */
  int sv = 120, tv = 121;
  for (int i = 0; i < n; i++) {
    mf.add(sv, i, 1, 0);
  }
  for (int i = 0; i < m; i++) {
    if (!(k & (1 << i)))
      continue;
    mf.add(MN + i, tv, c[i], 0);
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (!(k & (1 << j)))
        continue;
      mf.add(i, MN + j, 1,
             max(0, abs(ax[i] - bx[j]) + abs(ay[i] - by[j]) - md));
    }
  }
  int u = n;
  int res = mf.exec(sv, tv, u);
  return __builtin_popcount(k) * b * md + res;
}

int solve() {
  //    printf("solve n:%d\\n", n);
  /**
   * 0..MN human
   * MN..MN+MM pos
   * s:120 t:121 S:122 T:123
   */

  int res = 2 * 1e9;
  //    for (k = 0; k < (1<<m); k++) {
  for (k = 1; k < (1 << m); k++) {
    int fr = 0;
    int cc = 0;
    for (int i = 0; i < m; i++) {
      if (!(k & (1 << i)))
        continue;
      fr += f[i];
      cc += c[i];
    }
    if (cc < n)
      continue;
    int l = 0, r = 10000;
    while (r - l > 2) {
      int mdl = (l + l + r) / 3, mdr = (l + r + r) / 3;
      int dl = calc(mdl), dr = calc(mdr);
      //            printf("l:%d dl:%d r:%d dr:%d\\n", mdl, dl, mdr, dr);
      if (dl > dr) {
        l = mdl;
      } else {
        r = mdr;
      }
    }
    res = min(res, fr + min(calc(l), calc(r - 1)));
  }
  return res;
}

int main() {
  while (true) {
    cin >> n >> m >> b;
    if (!n && !m && !b)
      break;
    for (int i = 0; i < n; i++) {
      cin >> ax[i] >> ay[i];
    }
    for (int i = 0; i < m; i++) {
      cin >> bx[i] >> by[i] >> c[i] >> f[i];
    }
    cout << solve() << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_map>
#include <vector>

using namespace std;
typedef long long ll;

/**
 * Primal-Dual????????????????°??????¨???
 * ?????????????????´??°??§????????¨?§£??????????????¨?????¨???
 */

const int INF = 1 << 28;
template <int V> struct MinCostFlow {
  typedef int T;
  typedef pair<T, int> P;
  struct Edge {
    int to, rev;
    int cap;
    T cost;
  };
  vector<Edge> g[V];
  T h[V], dist[V];
  int pv[V], pe[V];
  void init() {
    for (int i = 0; i < V; i++) {
      g[i].clear();
    }
  }
  /// ????????????
  void add(int from, int to, int cap, T cost) {
    //        printf("add %d %d %d %d\\n", from, to, cap, cost);
    g[from].push_back(Edge{to, (int)g[to].size(), cap, cost});
    g[to].push_back(Edge{from, (int)g[from].size() - 1, 0, -cost});
  }
  /**
   * ????°??????¨???????¨??????????
   *
   * bell?????¢?????????????????????????????¨????????´????????????????????°????????§????§£??????????????¨?????¨???
   *
   * Params:
   *   s = ?§????
   *   t = ??????
   *   f = ?????????
   *   bell = ?????????????????????????????¨??????????????????
   */
  T exec(int s, int t, int &f, bool bell = false) {
    T res = 0;
    fill_n(h, V, 0);
    while (f > 0) {
      fill_n(dist, V, INF);
      dist[s] = 0;
      if (bell) {
        bell = false;
        bool update;
        do {
          update = false;
          for (int v = 0; v < V; v++) {
            if (dist[v] == INF)
              continue;
            for (int i = 0; i < (int)g[v].size(); i++) {
              Edge &e = g[v][i];
              if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
                dist[e.to] = dist[v] + e.cost;
                pv[e.to] = v;
                pe[e.to] = i;
                update = true;
              }
            }
          }
        } while (update);
      } else {
        priority_queue<P, vector<P>, greater<P>> que;
        que.push(P(0, s));
        while (!que.empty()) {
          P p = que.top();
          que.pop();
          int v = p.second;
          if (dist[v] < p.first)
            continue;
          for (int i = 0; i < (int)g[v].size(); i++) {
            Edge &e = g[v][i];
            if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
              dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
              pv[e.to] = v;
              pe[e.to] = i;
              que.push(P(dist[e.to], e.to));
            }
          }
        }
      }
      if (dist[t] == INF) {
        return res;
      }
      for (int v = 0; v < V; v++) {
        h[v] += dist[v];
      }

      T d = f;
      for (int v = t; v != s; v = pv[v]) {
        d = min(d, g[pv[v]][pe[v]].cap);
      }
      f -= d;
      res += d * h[t];
      for (int v = t; v != s; v = pv[v]) {
        Edge &e = g[pv[v]][pe[v]];
        e.cap -= d;
        g[v][e.rev].cap += d;
      }
    }
    return res;
  }
};

const int MN = 110;
const int MM = 6;
int n, m, b, k;
int ax[MN], ay[MN];
int bx[MM], by[MM], c[MM], f[MM];

MinCostFlow<130> mf;

int calc(int md) {
  //    printf("startcalc:%d\\n", md);
  mf.init();
  /**
   * 0..MN p
   * MN..MN+MM k
   * 120:s 121:t
   */
  int sv = 120, tv = 121;
  for (int i = 0; i < n; i++) {
    mf.add(sv, i, 1, 0);
  }
  for (int i = 0; i < m; i++) {
    if (!(k & (1 << i)))
      continue;
    mf.add(MN + i, tv, c[i], 0);
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (!(k & (1 << j)))
        continue;
      mf.add(i, MN + j, 1,
             max(0, abs(ax[i] - bx[j]) + abs(ay[i] - by[j]) - md));
    }
  }
  int u = n;
  int res = mf.exec(sv, tv, u);
  return __builtin_popcount(k) * b * md + res;
}

int solve() {
  //    printf("solve n:%d\\n", n);
  /**
   * 0..MN human
   * MN..MN+MM pos
   * s:120 t:121 S:122 T:123
   */

  int res = 2 * 1e9;
  //    for (k = 0; k < (1<<m); k++) {
  for (k = 1; k < (1 << m); k++) {
    int fr = 0;
    int cc = 0;
    for (int i = 0; i < m; i++) {
      if (!(k & (1 << i)))
        continue;
      fr += f[i];
      cc += c[i];
    }
    if (cc < n)
      continue;
    int l = 0, r = 10000;
    while (r - l > 2) {
      int mdl = (l + l + r) / 3, mdr = (l + r + r) / 3;
      int dl = calc(mdl), dr = calc(mdr);
      //            printf("l:%d dl:%d r:%d dr:%d\\n", mdl, dl, mdr, dr);
      if (dl > dr) {
        l = mdl;
      } else {
        r = mdr;
      }
    }
    res = min(res, fr + min(calc(l), calc(r - 1)));
  }
  return res;
}

int main() {
  while (true) {
    cin >> n >> m >> b;
    if (!n && !m && !b)
      break;
    for (int i = 0; i < n; i++) {
      cin >> ax[i] >> ay[i];
    }
    for (int i = 0; i < m; i++) {
      cin >> bx[i] >> by[i] >> c[i] >> f[i];
    }
    cout << solve() << endl;
  }
  return 0;
}