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

#include <bits/stdc++.h>
using namespace std;

template <class T> inline void chmin(T &a, const T &b) {
  if (a > b)
    a = b;
}
template <class T> inline void chmax(T &a, const T &b) {
  if (a < b)
    a = b;
}

constexpr int dx[] = {1, -1, 0, 0};
constexpr int dy[] = {0, 0, 1, -1};
constexpr int MAX_H = 60;
constexpr int MAX_W = 10;

int w, h;
int num;
vector<vector<int>> cnt;
vector<int> on, xl, xr;
bool visited[MAX_H][MAX_W];
int label[MAX_H][MAX_W];

inline bool out(int x, int y) { return x < 0 || y < 0 || x >= w || y >= h; }

void calc_unique_label(vector<string> &field) {
  const int h = field.size();
  const int w = field[0].size();

  num = 0;
  memset(label, -1, sizeof(label));
  for (int i = h - 1; i >= 0; --i) {
    for (int j = 0; j < w; ++j) {
      const char &c = field[i][j];
      if (label[i][j] == -1 && c != '.') {
        queue<pair<int, int>> que;
        que.push({j, i});
        label[i][j] = num;

        while (!que.empty()) {
          const int x = que.front().first;
          const int y = que.front().second;
          que.pop();

          for (int d = 0; d < 4; ++d) {
            const int nx = x + dx[d];
            const int ny = y + dy[d];
            if (out(nx, ny))
              continue;
            if (label[ny][nx] == -1 && field[ny][nx] == c) {
              label[ny][nx] = num;
              que.push({nx, ny});
            }
          }
        }

        ++num;
      }
    }
  }
}

void calc(int x, int y) {
  const int &l = label[y][x];
  visited[y][x] = true;
  ++cnt[l][x];

  for (int d = 0; d < 4; ++d) {
    const int nx = x + dx[d], ny = y + dy[d];
    if (out(nx, ny)) {
      if (d == 2) {
        chmin(xl[l], x);
        chmax(xr[l], x);
      }
      continue;
    }

    if (out(nx, ny))
      continue;
    if (label[ny][nx] != -1 && !visited[ny][nx]) {
      calc(nx, ny);
    }

    if (label[ny][nx] != l && label[ny][nx] != -1 && d == 2) {
      chmin(xl[l], x);
      chmax(xr[l], x);
      on[l] = label[ny][nx];
    }
  }
}

bool dfs(int idx) {
  for (int i = 0; i < num; ++i) {
    if (on[i] == idx) {
      if (!dfs(i))
        return false;
      for (int x = 0; x < w; ++x) {
        cnt[idx][x] += cnt[i][x];
      }
    }
  }

  int sum = 0;
  int weight_sum = 0;

  for (int x = 0; x < w; ++x) {
    sum += cnt[idx][x];
    weight_sum += cnt[idx][x] * x;
  }

  const double g = (double)weight_sum / sum;
  return xl[idx] - 0.5 < g && g < xr[idx] + 0.5;
}

int main() {
  while (cin >> w >> h && w) {
    vector<string> field(h);
    for (auto &e : field)
      cin >> e;
    calc_unique_label(field);
    cnt.assign(num, vector<int>(w, 0));
    on.assign(num, -1);
    xl.assign(num, w + 1);
    xr.assign(num, 0);
    memset(visited, false, sizeof(visited));

    for (int x = 0; x < w; ++x) {
      if (label[h - 1][x] == 0) {
        calc(x, h - 1);
        break;
      }
    }

    cout << (dfs(0) ? "STABLE" : "UNSTABLE") << endl;
  }

  return 0;
}

Error: 0
idx = 2
cnt[idx][x] = 0
cnt[idx][x] = 0
cnt[idx][x] = 2
cnt[idx][x] = 2
g = 2.5
xl[idx] = 2
xr[idx] = 3
idx = 1
cnt[idx][x] = 1
cnt[idx][x] = 1
cnt[idx][x] = 3
cnt[idx][x] = 3
g = 2
xl[idx] = 2
xr[idx] = 2
idx = 0
cnt[idx][x] = 1
cnt[idx][x] = 2
cnt[idx][x] = 5
cnt[idx][x] = 4
g = 2
xl[idx] = 1
xr[idx] = 3
idx = 2
cnt[idx][x] = 1
cnt[idx][x] = 3
cnt[idx][x] = 0
cnt[idx][x] = 0
cnt[idx][x] = 0
g = 0.75
xl[idx] = 1
xr[idx] = 1
idx = 3
cnt[idx][x] = 0
cnt[idx][x] = 0
cnt[idx][x] = 0
cnt[idx][x] = 0
cnt[idx][x] = 4
g = 4
xl[idx] = 4
xr[idx] = 4
idx = 1
cnt[idx][x] = 1
cnt[idx][x] = 4
cnt[idx][x] = 1
cnt[idx][x] = 1
cnt[idx][x] = 5
g = 2.41667
xl[idx] = 2
xr[idx] = 4
idx = 0
cnt[idx][x] = 1
cnt[idx][x] = 4
cnt[idx][x] = 2
cnt[idx][x] = 3
cnt[idx][x] = 6
g = 2.5625
xl[idx] = 3
xr[idx] = 3
idx = 2
cnt[idx][x] = 0
cnt[idx][x] = 3
cnt[idx][x] = 1
g = 1.25
xl[idx] = 1
xr[idx] = 1
idx = 1
cnt[idx][x] = 3
cnt[idx][x] = 4
cnt[idx][x] = 1
g = 0.75
xl[idx] = 1
xr[idx] = 1
idx = 0
cnt[idx][x] = 3
cnt[idx][x] = 6
cnt[idx][x] = 3
g = 1
xl[idx] = 1
xr[idx] = 2
idx = 1
cnt[idx][x] = 1
cnt[idx][x] = 1
cnt[idx][x] = 1
cnt[idx][x] = 1
g = 1.5
xl[idx] = 2
xr[idx] = 3
idx = 2
cnt[idx][x] = 2
cnt[idx][x] = 2
cnt[idx][x] = 0
cnt[idx][x] = 0
g = 0.5
xl[idx] = 0
xr[idx] = 1
idx = 1
cnt[idx][x] = 3
cnt[idx][x] = 4
cnt[idx][x] = 1
cnt[idx][x] = 0
g = 0.75
xl[idx] = 1
xr[idx] = 2
idx = 0
cnt[idx][x] = 3
cnt[idx][x] = 5
cnt[idx][x] = 3
cnt[idx][x] = 1
g = 1.16667
xl[idx] = 1
xr[idx] = 2
idx = 1
cnt[idx][x] = 2
cnt[idx][x] = 1
cnt[idx][x] = 1
g = 0.75
xl[idx] = 0
xr[idx] = 2
idx = 0
cnt[idx][x] = 3
cnt[idx][x] = 2
cnt[idx][x] = 3
g = 1
xl[idx] = 0
xr[idx] = 2
idx = 1
cnt[idx][x] = 2
cnt[idx][x] = 2
cnt[idx][x] = 0
g = 0.5
xl[idx] = 1
xr[idx] = 1
idx = 1
cnt[idx][x] = 0
cnt[idx][x] = 2
cnt[idx][x] = 2
g = 1.5
xl[idx] = 1
xr[idx] = 1
idx = 2
cnt[idx][x] = 1
cnt[idx][x] = 3
g = 0.75
xl[idx] = 1
xr[idx] = 1
idx = 1
cnt[idx][x] = 4
cnt[idx][x] = 4
g = 0.5
xl[idx] = 1
xr[idx] = 1
idx = 0
cnt[idx][x] = 2
cnt[idx][x] = 2
g = 0.5
xl[idx] = 1
xr[idx] = 1


Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define dump(a) (cerr << #a << " = " << (a) << endl)

template <class T> inline void chmin(T &a, const T &b) {
  if (a > b)
    a = b;
}
template <class T> inline void chmax(T &a, const T &b) {
  if (a < b)
    a = b;
}

constexpr int dx[] = {1, -1, 0, 0};
constexpr int dy[] = {0, 0, 1, -1};
constexpr int MAX_H = 60;
constexpr int MAX_W = 10;

int w, h;
int num;
vector<vector<int>> cnt;
vector<int> on, xl, xr;
bool visited[MAX_H][MAX_W];
int label[MAX_H][MAX_W];

inline bool out(int x, int y) { return x < 0 || y < 0 || x >= w || y >= h; }

void calc_unique_label(vector<string> &field) {
  const int h = field.size();
  const int w = field[0].size();

  num = 0;
  memset(label, -1, sizeof(label));
  for (int i = h - 1; i >= 0; --i) {
    for (int j = 0; j < w; ++j) {
      const char &c = field[i][j];
      if (label[i][j] == -1 && c != '.') {
        queue<pair<int, int>> que;
        que.push({j, i});
        label[i][j] = num;

        while (!que.empty()) {
          const int x = que.front().first;
          const int y = que.front().second;
          que.pop();

          for (int d = 0; d < 4; ++d) {
            const int nx = x + dx[d];
            const int ny = y + dy[d];
            if (out(nx, ny))
              continue;
            if (label[ny][nx] == -1 && field[ny][nx] == c) {
              label[ny][nx] = num;
              que.push({nx, ny});
            }
          }
        }

        ++num;
      }
    }
  }
}

void calc(int x, int y) {
  const int &l = label[y][x];
  visited[y][x] = true;
  ++cnt[l][x];

  for (int d = 0; d < 4; ++d) {
    const int nx = x + dx[d], ny = y + dy[d];
    if (out(nx, ny)) {
      if (d == 2) {
        chmin(xl[l], x);
        chmax(xr[l], x);
      }
      continue;
    }

    if (out(nx, ny))
      continue;
    if (label[ny][nx] != -1 && !visited[ny][nx]) {
      calc(nx, ny);
    }

    if (label[ny][nx] != l && label[ny][nx] != -1 && d == 2) {
      chmin(xl[l], x);
      chmax(xr[l], x);
      on[l] = label[ny][nx];
    }
  }
}

bool dfs(int idx) {
  for (int i = 0; i < num; ++i) {
    if (on[i] == idx) {
      if (!dfs(i))
        return false;
      for (int x = 0; x < w; ++x) {
        cnt[idx][x] += cnt[i][x];
      }
    }
  }

  int sum = 0;
  int weight_sum = 0;

  for (int x = 0; x < w; ++x) {
    sum += cnt[idx][x];
    weight_sum += cnt[idx][x] * x;
  }

  const double g = (double)weight_sum / sum;

  dump(idx);
  for (int x = 0; x < w; ++x) {
    dump(cnt[idx][x]);
  }
  dump(g);
  dump(xl[idx]);
  dump(xr[idx]);

  return xl[idx] - 0.5 < g && g < xr[idx] + 0.5;
}

int main() {
  while (cin >> w >> h && w) {
    vector<string> field(h);
    for (auto &e : field)
      cin >> e;
    calc_unique_label(field);
    cnt.assign(num, vector<int>(w, 0));
    on.assign(num, -1);
    xl.assign(num, w + 1);
    xr.assign(num, 0);
    memset(visited, false, sizeof(visited));

    for (int x = 0; x < w; ++x) {
      if (label[h - 1][x] == 0) {
        calc(x, h - 1);
        break;
      }
    }

    cout << (dfs(0) ? "STABLE" : "UNSTABLE") << endl;
  }

  return 0;
}