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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <queue>
#include <vector>

using namespace std;

const int N = 200050;

int p, r, t, a[510], m[510][510], s[510][510], b[510], u[N], v[N];
bool vis[510];

bool check(int mid) {
  queue<int> q;
  for (int i = 0; i < p; i++) {
    vis[i] = false;
    for (int j = 0; j < r; j++) {
      s[i][j] = m[i][j];
    }
  }
  for (int i = 0; i < r; i++) {
    b[i] = a[i];
  }
  for (int i = 0; i <= mid; i++) {
    b[v[i]]--;
    s[u[i]][v[i]]--;
    assert(u[i] < p);
    assert(v[i] < r);
    // assert(b[v[i]] >= 0);
    assert(s[u[i]][v[i]] >= 0);
  }
  // printf("debg %d ..\\n", mid);
  for (int i = 0; i < p; i++) {
    for (int j = 0; j < r; j++) {
      // printf("%d ", s[i][j]);
    }
    // puts("");
  }
  for (int i = 0; i < p; i++) {
    bool ok = true;
    bool eq = true;
    for (int j = 0; j < r; j++) {
      if (s[i][j] != 0) {
        eq = false;
        break;
      }
    }
    for (int j = 0; j < r; j++) {
      if (s[i][j] > b[j]) {
        ok = false;
        break;
      }
    }
    if (ok || eq) {
      vis[i] = true;
      q.push(i);
    }
  }
  while (!q.empty()) {
    int now = q.front();
    q.pop();
    for (int i = 0; i < r; i++) {
      b[i] += m[now][i] - s[now][i];
    }
    for (int i = 0; i < p; i++) {
      if (vis[i]) {
        continue;
      }
      bool ok = true;
      bool eq = true;
      for (int j = 0; j < r; j++) {
        if (s[i][j] != 0) {
          eq = false;
          break;
        }
      }
      for (int j = 0; j < r; j++) {
        if (s[i][j] > b[j]) {
          ok = false;
          break;
        }
      }
      if (ok || eq) {
        vis[i] = true;
        q.push(i);
      }
    }
  }
  for (int i = 0; i < p; i++) {
    if (!vis[i]) {
      return false;
    }
  }
  return true;
}

int main() {

  while (scanf("%d %d %d", &p, &r, &t) != EOF) {
    for (int i = 0; i < r; i++) {
      scanf("%d", &a[i]);
    }
    for (int i = 0; i < p; i++) {
      for (int j = 0; j < r; j++) {
        scanf("%d", &m[i][j]);
      }
    }
    for (int i = 0; i < t; i++) {
      scanf("%d %d", &u[i], &v[i]);
      u[i]--;
      v[i]--;
    }
    if (check(t - 1)) {
      puts("-1");
      continue;
    }
    int lo = -1;
    int hi = t - 1;
    for (int i = 0; i + 1 < t && i < 100; i++) {
      // printf("%d %d %d\\n", i, check(i), check(i + 1));
      // assert(check(i) >= check(i + 1));
    }
    while (lo <= hi) {
      int mid = (lo + hi) / 2;
      if (check(mid)) {
        lo = mid + 1;
      } else {
        hi = mid - 1;
      }
    }
    printf("%d\\n", lo + 1);
  }

  return 0;
}

Error: -6
a5e2e523-cbca-4c4c-804a-810c7309d11b.out: /home/alex/Documents/bug-detection/input/Project_CodeNet/data/p00940/C++/s172523639.cpp:30: bool check(int): Assertion `b[v[i]] >= 0' failed.


Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <queue>
#include <vector>

using namespace std;

const int N = 200050;

int p, r, t, a[510], m[510][510], s[510][510], b[510], u[N], v[N];
bool vis[510];

bool check(int mid) {
  queue<int> q;
  for (int i = 0; i < p; i++) {
    vis[i] = false;
    for (int j = 0; j < r; j++) {
      s[i][j] = m[i][j];
    }
  }
  for (int i = 0; i < r; i++) {
    b[i] = a[i];
  }
  for (int i = 0; i <= mid; i++) {
    b[v[i]]--;
    s[u[i]][v[i]]--;
    assert(u[i] < p);
    assert(v[i] < r);
    assert(b[v[i]] >= 0);
    assert(s[u[i]][v[i]] >= 0);
  }
  for (int i = 0; i < p; i++) {
    bool ok = true;
    for (int j = 0; j < r; j++) {
      if (s[i][j] > b[j]) {
        ok = false;
        break;
      }
    }
    if (ok) {
      vis[i] = true;
      q.push(i);
    }
  }
  while (!q.empty()) {
    int now = q.front();
    q.pop();
    for (int i = 0; i < r; i++) {
      b[i] += m[now][i] - s[now][i];
    }
    for (int i = 0; i < p; i++) {
      if (vis[i]) {
        continue;
      }
      bool ok = true;
      for (int j = 0; j < r; j++) {
        if (s[i][j] > b[j]) {
          ok = false;
          break;
        }
      }
      if (ok) {
        vis[i] = true;
        q.push(i);
      }
    }
  }
  for (int i = 0; i < p; i++) {
    if (!vis[i]) {
      return false;
    }
  }
  return true;
}

int main() {

  while (scanf("%d %d %d", &p, &r, &t) != EOF) {
    for (int i = 0; i < r; i++) {
      scanf("%d", &a[i]);
    }
    for (int i = 0; i < p; i++) {
      for (int j = 0; j < r; j++) {
        scanf("%d", &m[i][j]);
      }
    }
    for (int i = 0; i < t; i++) {
      scanf("%d %d", &u[i], &v[i]);
      u[i]--;
      v[i]--;
    }
    if (check(t - 1)) {
      puts("-1");
      continue;
    }
    int lo = -1;
    int hi = t - 1;
    for (int i = 0; i < t && i < 100; i++) {
      assert(check(i) >= check(i + 1));
    }
    while (lo <= hi) {
      int mid = (lo + hi) / 2;
      if (check(mid)) {
        lo = mid + 1;
      } else {
        hi = mid - 1;
      }
    }
    printf("%d\\n", lo + 1);
  }

  return 0;
}