Problem p00288 (C++) — buggy submission, verdict: Runtime Error

#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;

int nlz(int x) {
  if (x == 0)
    return 32;
  return __builtin_clz(x);
}
struct RadixHeap {
  typedef pair<int, int> P;
  vector<P> v[32];
  bool f;
  int mi, sz;
  RadixHeap() {
    mi = sz = 0;
    f = false;
  }
  void first(int x, int p) {
    sz = 1;
    mi = x;
    v[0].push_back(P(x, p));
  }
  void push(int x, int p) {
    if (!f) {
      f = true;
      first(x, p);
      return;
    }
    assert(mi <= x);
    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; }
  void clear() {
    mi = sz = 0;
    for (int i = 0; i < 32; i++) {
      v[i].clear();
    }
  }
};

const int INF = 1 << 27;
template <int V> struct MinCostFlowOptimize {
  typedef int T;
  typedef pair<T, int> P;
  //    using T = int;
  //    using P = pair<T, int>;
  struct Edge {
    int to, rev;
    int cap;
    T cost;
  };
  vector<Edge> g[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, (T)(-cost)});
  }

  T h[V], dist[V];
  bool used[V];
  Edge *prev[V];
  T exec(int s, int t, int &f) {
    T res = 0;
    fill_n(h, V, 0);
    while (f > 0) {
      fill_n(dist, V, INF);
      fill_n(used, V, false);
      dist[s] = 0;
      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 (v == t)
          break;
        if (used[v])
          continue;
        used[v] = true;
        int hv = h[v], distv = dist[v];
        for (Edge &e : g[v]) {
          if (!e.cap)
            continue;
          T ee = e.cost - hv + h[e.to];
          if (dist[e.to] > distv + ee) {
            dist[e.to] = distv + ee;
            prev[e.to] = &e;
            que.push(P(dist[e.to], e.to));
          }
        }
      }
      if (dist[t] == INF) {
        return res;
      }
      for (int v = 0; v < V; v++) {
        if (dist[v] >= dist[t])
          continue;
        h[v] += dist[t] - dist[v];
      }
      T d = f;
      for (int v = t; v != s; v = g[v][prev[v]->rev].to) {
        d = min(d, prev[v]->cap);
      }
      f -= d;
      res += d * (h[s] - h[t]);
      for (int v = t; v != s; v = g[v][prev[v]->rev].to) {
        prev[v]->cap -= d;
        g[v][prev[v]->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];

MinCostFlowOptimize<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: -6
8fa8176b-6936-4394-a9a5-afb2385ac603.out: /home/alex/Documents/bug-detection/input/Project_CodeNet/data/p00288/C++/s702579323.cpp:37: void RadixHeap::push(int, int): Assertion `mi <= x' failed.


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;

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;
    }
    assert(mi <= x);
    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; }
  void clear() {
    mi = sz = 0;
    for (int i = 0; i < 32; i++) {
      v[i].clear();
    }
  }
};

const int INF = 1 << 27;
template <int V> struct MinCostFlowOptimize {
  typedef int T;
  typedef pair<T, int> P;
  //    using T = int;
  //    using P = pair<T, int>;
  struct Edge {
    int to, rev;
    int cap;
    T cost;
  };
  vector<Edge> g[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, (T)(-cost)});
  }

  T h[V], dist[V];
  bool used[V];
  Edge *prev[V];
  T exec(int s, int t, int f) {
    T res = 0;
    fill_n(h, V, 0);
    while (f > 0) {
      fill_n(dist, V, INF);
      fill_n(used, V, false);
      dist[s] = 0;
      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 (v == t)
          break;
        if (used[v])
          continue;
        used[v] = true;
        int hv = h[v], distv = dist[v];
        for (Edge &e : g[v]) {
          if (!e.cap)
            continue;
          T ee = e.cost - hv + h[e.to];
          if (dist[e.to] > distv + ee) {
            dist[e.to] = distv + ee;
            prev[e.to] = &e;
            que.push(P(dist[e.to], e.to));
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      for (int v = 0; v < V; v++) {
        if (dist[v] >= dist[t])
          continue;
        h[v] += dist[t] - dist[v];
      }
      T d = f;
      for (int v = t; v != s; v = g[v][prev[v]->rev].to) {
        d = min(d, prev[v]->cap);
      }
      f -= d;
      res += d * (h[s] - h[t]);
      for (int v = t; v != s; v = g[v][prev[v]->rev].to) {
        prev[v]->cap -= d;
        g[v][prev[v]->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];

MinCostFlowOptimize<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;
}