Problem p00749 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>/*{{{*/
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;
typedef long long int LL;
typedef complex<double> P;

static const double PI(3.14159265358979323846);
static const double EPS(1e-10);

typedef long long int ll;
typedef unsigned long long int ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;

inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}

#define FOR(i, b, e) for (typeof(b) i = (b); assert((i) <= (e)), i != (e); ++i)

#define OPOVER(_op, _type) inline bool operator _op(const _type &t) const

#define arrsz(a) (sizeof(a) / sizeof(a[0]))

#define F first
#define S second
#define MP(a, b) make_pair(a, b)

#define SZ(a) ((ll)a.size())
#define PB(e) push_back(e)
#define SORT(v) sort((v).begin(), (v).end())
#define RSORT(v) sort((v).rbegin(), (v).rend())

#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EACH(t, i, c) for (t::iterator i = (c).begin(); i != (c).end(); ++i)
#define EXIST(s, e) ((s).find(e) != (s).end())

#define BIT(n) (1ULL << (n))
#define BITOF(n, m) ((n) >> (m)&1)

#define RANGE(a, b, c) ((a) <= (b) && (b) <= (c))

#define DEBUG_ON_

#ifdef DEBUG_ON
#define dprt(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#define darr(a)                                                                \
  copy((a), (a) + arrsz(a), ostream_iterator<int>(cerr, " "));                 \
  cerr << endl
#define darr_range(a, f, t)                                                    \
  copy((a) + (f), (a) + (t), ostream_iterator<int>(cerr, " "));                \
  cerr << endl
#define dvec(v)                                                                \
  copy(ALL(v), ostream_iterator<int>(cerr, " "));                              \
  cerr << endl
#define darr2(a, n, m)                                                         \
  FOR(i, 0, (n)) { darr_range((a)[i], 0, (m)); }
#define dvec2(v)                                                               \
  FOR(i, 0, SZ(v)) { dvec((v)[i]); }
#define WAIT()                                                                 \
  {                                                                            \
    string _wait_;                                                             \
    cerr << "(hit return to continue)" << endl;                                \
    getline(cin, _wait_);                                                      \
  }
#else
#define dprt(fmt, ...)
#define darr(a)
#define darr_range(a, f, t)
#define dvec(v)
#define darr2(a, n, m)
#define dvec2(v)
#define WAIT()
#endif
/*}}}*/

struct block {
  int x;
  int y;
};
struct piece {
  int id;
  int xl;
  int xr;
  vector<block> blocks;
  vector<piece *> upper_pieces;
};

int w, h;
int field[10][60];
vector<piece> pieces;

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
void create_piece(piece *p, int y, int x) /*{{{*/
{
  int id = field[y][x];
  field[y][x] = -p->id;
  block b;
  b.y = y;
  b.x = x;
  p->blocks.PB(b);

  FOR(d, 0, 4) {
    int yd = y + dy[d];
    int xd = x + dx[d];
    if (RANGE(0, yd, h - 1) && RANGE(0, xd, w - 1))
      ;
    else
      continue;

    if (field[yd][xd] == id) {
      create_piece(p, yd, xd);
    }
  }
} /*}}}*/

void search_piece() /*{{{*/
{
  int pnum = 0;
  FOR(i, 0, h) {
    FOR(j, 0, w) {
      if (RANGE('1', field[i][j], '9')) {
        piece p;
        p.id = pnum;
        create_piece(&p, i, j);
        pieces.PB(p);
        ++pnum;
      }
    }
  }

  set<int> done;
  FOR(i, 0, h) {
    FOR(j, 0, w) {
      if (field[i][j] <= 0 && !EXIST(done, field[i][j])) {
        done.insert(field[i][j]);
        int id = abs(field[i][j]);
        piece *p = &pieces[id];
        // cerr << "check #" << p->id << endl;

        int lowest_y = -1;
        int xl = 100, xr = -100;
        FOR(i, 0, p->blocks.size()) {
          block b = p->blocks[i];

          if (b.y == h - 1 ||
              (field[b.y + 1][b.x] <= 0 && field[b.y + 1][b.x] != -p->id)) {
            xl = min(xl, b.x);
            xr = max(xr, b.x + 1);
          }
          p->xl = xl;
          p->xr = xr;

          if (b.y - 1 >= 0) {
            if (field[b.y - 1][b.x] <= 0 && abs(field[b.y - 1][b.x]) != p->id) {
              bool t = true;
              FOR(i, 0, p->upper_pieces.size()) {
                if (p->upper_pieces[i]->id == abs(field[b.y - 1][b.x])) {
                  t = false;
                }
              }
              if (t) {
                // cerr << "append #" << pieces[abs(field[b.y-1][b.x])].id << "
                // to #" << p->id << "'s upper" << endl;
                p->upper_pieces.PB(&pieces[abs(field[b.y - 1][b.x])]);
              }
            }
          }
        }
      }
    }
  }
} /*}}}*/

bool dfs(piece *p, vector<block> *blocks) {
  // cerr << endl << "check piece #" << abs(p->id) << endl;
  vector<block> upper_blocks;
  FOR(i, 0, p->upper_pieces.size()) {
    piece *up = p->upper_pieces[i];
    // cerr << "#" << up->id << " is upper" << endl;
    if (!dfs(up, &upper_blocks)) {
      return false;
    }
  }
  // merge
  FOR(i, 0, p->blocks.size()) { upper_blocks.PB(p->blocks[i]); }
  double mx = 0, my = 0;
  FOR(i, 0, upper_blocks.size()) {
    block b = upper_blocks[i];
    // cerr << "block at (" << b.x << ", " << b.y << ")" << endl;
    mx += b.x + 0.5;
    my += b.y + 0.5;
  }
  mx /= (double)upper_blocks.size();
  my /= (double)upper_blocks.size();

  // cerr << "xl: " << p->xl << ", xr: " << p->xr << ", mx: " << mx << endl;
  if (p->xl < mx && mx < p->xr) {
    FOR(i, 0, upper_blocks.size()) { (*blocks).PB(upper_blocks[i]); }
    // cerr << "#" << p->id << " is stable" << endl;
    return true;
  } else {
    return false;
  }
}

int main(int argc, char const *argv[]) {
  while (cin >> w >> h, w || h) {
    FOR(i, 0, pieces.size()) {
      pieces[i].blocks.clear();
      pieces[i].upper_pieces.clear();
    }
    pieces.clear();
    FOR(i, 0, h) {
      FOR(j, 0, w) {
        char c;
        cin >> c;
        field[i][j] = c;
      }
    }
    search_piece();

    int lowest = 0;
    FOR(i, 0, w) {
      if (field[h - 1][i] <= 0) {
        lowest = abs(field[h - 1][i]);
        break;
      }
    }
    // cerr << "lowest is #" << lowest << endl;
    vector<block> b;
    darr2(field, h, w);
    if (dfs(&pieces[lowest], &b)) {
      cout << "STABLE" << endl;
    } else {
      cout << "UNSTABLE" << endl;
    }
  }

  return 0;
}

Fixed submission:
#include <algorithm>/*{{{*/
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;
typedef long long int LL;
typedef complex<double> P;

static const double PI(3.14159265358979323846);
static const double EPS(1e-10);

typedef long long int ll;
typedef unsigned long long int ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;

inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}

#define FOR(i, b, e) for (typeof(b) i = (b); assert((i) <= (e)), i != (e); ++i)

#define OPOVER(_op, _type) inline bool operator _op(const _type &t) const

#define arrsz(a) (sizeof(a) / sizeof(a[0]))

#define F first
#define S second
#define MP(a, b) make_pair(a, b)

#define SZ(a) ((ll)a.size())
#define PB(e) push_back(e)
#define SORT(v) sort((v).begin(), (v).end())
#define RSORT(v) sort((v).rbegin(), (v).rend())

#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EACH(t, i, c) for (t::iterator i = (c).begin(); i != (c).end(); ++i)
#define EXIST(s, e) ((s).find(e) != (s).end())

#define BIT(n) (1ULL << (n))
#define BITOF(n, m) ((n) >> (m)&1)

#define RANGE(a, b, c) ((a) <= (b) && (b) <= (c))

#define DEBUG_ON_

#ifdef DEBUG_ON
#define dprt(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#define darr(a)                                                                \
  copy((a), (a) + arrsz(a), ostream_iterator<int>(cerr, " "));                 \
  cerr << endl
#define darr_range(a, f, t)                                                    \
  copy((a) + (f), (a) + (t), ostream_iterator<int>(cerr, " "));                \
  cerr << endl
#define dvec(v)                                                                \
  copy(ALL(v), ostream_iterator<int>(cerr, " "));                              \
  cerr << endl
#define darr2(a, n, m)                                                         \
  FOR(i, 0, (n)) { darr_range((a)[i], 0, (m)); }
#define dvec2(v)                                                               \
  FOR(i, 0, SZ(v)) { dvec((v)[i]); }
#define WAIT()                                                                 \
  {                                                                            \
    string _wait_;                                                             \
    cerr << "(hit return to continue)" << endl;                                \
    getline(cin, _wait_);                                                      \
  }
#else
#define dprt(fmt, ...)
#define darr(a)
#define darr_range(a, f, t)
#define dvec(v)
#define darr2(a, n, m)
#define dvec2(v)
#define WAIT()
#endif
/*}}}*/

struct block {
  int x;
  int y;
};
struct piece {
  int id;
  int xl;
  int xr;
  vector<block> blocks;
  vector<piece *> upper_pieces;
};

int w, h;
int field[60][10];
vector<piece> pieces;

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
void create_piece(piece *p, int y, int x) /*{{{*/
{
  int id = field[y][x];
  field[y][x] = -p->id;
  block b;
  b.y = y;
  b.x = x;
  p->blocks.PB(b);

  FOR(d, 0, 4) {
    int yd = y + dy[d];
    int xd = x + dx[d];
    if (RANGE(0, yd, h - 1) && RANGE(0, xd, w - 1))
      ;
    else
      continue;

    if (field[yd][xd] == id) {
      create_piece(p, yd, xd);
    }
  }
} /*}}}*/

void search_piece() /*{{{*/
{
  int pnum = 0;
  FOR(i, 0, h) {
    FOR(j, 0, w) {
      if (RANGE('1', field[i][j], '9')) {
        piece p;
        p.id = pnum;
        create_piece(&p, i, j);
        pieces.PB(p);
        ++pnum;
      }
    }
  }

  set<int> done;
  FOR(i, 0, h) {
    FOR(j, 0, w) {
      if (field[i][j] <= 0 && !EXIST(done, field[i][j])) {
        done.insert(field[i][j]);
        int id = abs(field[i][j]);
        piece *p = &pieces[id];
        // cerr << "check #" << p->id << endl;

        int lowest_y = -1;
        int xl = 100, xr = -100;
        FOR(i, 0, p->blocks.size()) {
          block b = p->blocks[i];

          if (b.y == h - 1 ||
              (field[b.y + 1][b.x] <= 0 && field[b.y + 1][b.x] != -p->id)) {
            xl = min(xl, b.x);
            xr = max(xr, b.x + 1);
          }
          p->xl = xl;
          p->xr = xr;

          if (b.y - 1 >= 0) {
            if (field[b.y - 1][b.x] <= 0 && abs(field[b.y - 1][b.x]) != p->id) {
              bool t = true;
              FOR(i, 0, p->upper_pieces.size()) {
                if (p->upper_pieces[i]->id == abs(field[b.y - 1][b.x])) {
                  t = false;
                }
              }
              if (t) {
                // cerr << "append #" << pieces[abs(field[b.y-1][b.x])].id << "
                // to #" << p->id << "'s upper" << endl;
                p->upper_pieces.PB(&pieces[abs(field[b.y - 1][b.x])]);
              }
            }
          }
        }
      }
    }
  }
} /*}}}*/

bool dfs(piece *p, vector<block> *blocks) {
  // cerr << endl << "check piece #" << abs(p->id) << endl;
  vector<block> upper_blocks;
  FOR(i, 0, p->upper_pieces.size()) {
    piece *up = p->upper_pieces[i];
    // cerr << "#" << up->id << " is upper" << endl;
    if (!dfs(up, &upper_blocks)) {
      return false;
    }
  }
  // merge
  FOR(i, 0, p->blocks.size()) { upper_blocks.PB(p->blocks[i]); }
  double mx = 0, my = 0;
  FOR(i, 0, upper_blocks.size()) {
    block b = upper_blocks[i];
    // cerr << "block at (" << b.x << ", " << b.y << ")" << endl;
    mx += b.x + 0.5;
    my += b.y + 0.5;
  }
  mx /= (double)upper_blocks.size();
  my /= (double)upper_blocks.size();

  // cerr << "xl: " << p->xl << ", xr: " << p->xr << ", mx: " << mx << endl;
  if (p->xl < mx && mx < p->xr) {
    FOR(i, 0, upper_blocks.size()) { (*blocks).PB(upper_blocks[i]); }
    // cerr << "#" << p->id << " is stable" << endl;
    return true;
  } else {
    return false;
  }
}

int main(int argc, char const *argv[]) {
  while (cin >> w >> h, w || h) {
    FOR(i, 0, pieces.size()) {
      pieces[i].blocks.clear();
      pieces[i].upper_pieces.clear();
    }
    pieces.clear();
    FOR(i, 0, h) {
      FOR(j, 0, w) {
        char c;
        cin >> c;
        field[i][j] = c;
      }
    }
    search_piece();

    int lowest = 0;
    FOR(i, 0, w) {
      if (field[h - 1][i] <= 0) {
        lowest = abs(field[h - 1][i]);
        break;
      }
    }
    // cerr << "lowest is #" << lowest << endl;
    vector<block> b;
    darr2(field, h, w);
    if (dfs(&pieces[lowest], &b)) {
      cout << "STABLE" << endl;
    } else {
      cout << "UNSTABLE" << endl;
    }
  }

  return 0;
}