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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
#define REP(i, j) for (int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for (int i = (int)(j); i < (int)(k); ++i)
#define P pair<int, int>
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
const int MAX_N = 61;

int my[] = {-1, 1, 0, 0};
int mx[] = {0, 0, 1, -1};

class C {
public:
  int cnt, sum, parent;
  double p_xl, p_xr;
  vector<P> cs;
  C(int _p, vector<P> _cs, double _p_xl, double _p_xr) {
    parent = _p;
    cs = _cs;
    cnt = (int)(cs.size());
    sum = 0;
    REP(i, cs.size()) { sum += cs[i].second; }
    p_xl = _p_xl;
    p_xr = _p_xr;
  }
  C(){};
};

int W, H;
string f[MAX_N];
vector<C> blocks;
vector<set<int>> children;

void find_block(int y, int x, char c, vector<P> &v) {
  f[y][x] = '.';
  v.push_back(P(y, x));
  REP(i, 4) {
    int ny = y + my[i], nx = x + mx[i];
    if (ny >= 0 && nx >= 0 && ny < H && nx < W && f[ny][nx] == c)
      find_block(ny, nx, c, v);
  }
}

int find_parent(int now) {
  int ret = -1;
  vector<P> cs;
  REP(i, blocks.size()) {
    if (i == now)
      continue;
    REP(j, blocks[now].cs.size()) {
      REP(k, blocks[i].cs.size()) {
        int now_y = blocks[now].cs[j].first;
        int now_x = blocks[now].cs[j].second;
        int block_y = blocks[i].cs[k].first;
        int block_x = blocks[i].cs[k].second;
        if (now_x == block_x && now_y + 1 == block_y) {
          ret = i;
          cs.push_back(P(block_y, block_x));
          // blocks[now].p_xl = 100.0;
          // blocks[now].p_xr = -1.0;
          // REP(j, blocks[i].cs.size()){
          // TODO: 以下のif文で本当に合ってる？
          // if(blocks[i].cs[j].first == block_y){
          //   blocks[now].p_xl = min(blocks[now].p_xl,
          //   (double)blocks[i].cs[j].second - 0.5); blocks[now].p_xr =
          //   max(blocks[now].p_xr, (double)blocks[i].cs[j].second + 0.5);
          // }
          //}
          // return i;
        }
      }
    }
  }
  if (ret != -1) {
    double xl = 100, xr = -1;
    REP(i, cs.size()) {
      xl = min(xl, cs[i].second - 0.5);
      xr = max(xr, cs[i].second + 0.5);
    }
    blocks[now].p_xl = xl;
    blocks[now].p_xr = xr;
  }
  return ret;
  // return -1;
}

void find_children(int now, set<int> &c) {
  REP(i, blocks.size()) {
    if (blocks[i].parent == now && c.find(i) == c.end()) {
      c.insert(i);
      find_children(i, c);
    }
  }
}

bool is_valid_tree(int now) {
  int a = blocks[now].sum, b = blocks[now].cnt;
  for (set<int>::iterator it = children[now].begin(); it != children[now].end();
       ++it) {
    C block = blocks[(*it)];
    a += block.sum;
    b += block.cnt;
  }
  double m = (double)a / b;
  // cout <<now <<" : " <<blocks[now].p_xl <<", " <<m <<", " <<blocks[now].p_xr
  // <<endl;
  return (m > blocks[now].p_xl && m < blocks[now].p_xr ? true : false);
}

int main() {
  while (cin >> W >> H && H) {
    blocks.clear();
    REP(i, H) cin >> f[i];
    REP(i, W) {
      if (isdigit(f[H - 1][i])) {
        vector<P> cs;
        find_block(H - 1, i, f[H - 1][i], cs);
        double xl = 100, xr = -1;
        REP(k, cs.size()) {
          if (cs[k].first == H - 1) {
            xl = min(xl, cs[k].second - 0.5);
            xr = max(xl, cs[k].second + 0.5);
          }
        }
        C tmp = C(-1, cs, xl, xr);
        blocks.push_back(tmp);
      }
    }
    // REP(i, blocks[0].cs.size()) cout <<blocks[0].cs[i].first <<", "
    // <<blocks[0].cs[i].second <<", " <<blocks[0].p_xl <<", " <<blocks[0].p_xr
    // <<endl;
    for (int i = H - 1; i >= 0; --i) {
      for (int j = W - 1; j >= 0; --j) {
        if (isdigit(f[i][j])) {
          vector<P> cs;
          find_block(i, j, f[i][j], cs);
          blocks.push_back(C(-1, cs, -1, 100));
        }
      }
    }
    FOR(i, 1, blocks.size())
    blocks[i].parent = find_parent(i);
    // REP(i, blocks.size()){
    //   cout <<i <<" : " <<endl;
    //   cout <<"parent = " <<blocks[i].parent <<", xl = " <<blocks[i].p_xl <<",
    //   xr = " <<blocks[i].p_xr <<endl; REP(j, blocks[i].cs.size()) cout
    //   <<blocks[i].cs[j].first <<", " <<blocks[i].cs[j].second <<" | "; cout
    //   <<endl;
    // }
    children = vector<set<int>>((int)(blocks.size()));
    FOR(i, 1, blocks.size()) children[0].insert(i);
    FOR(i, 1, blocks.size()) find_children(i, children[i]);
    // REP(i, blocks.size()){
    //   cout <<i <<" : ";
    //   for(set<int>::iterator it = children[i].begin(); it !=
    //   children[i].end(); ++it) cout <<(*it) <<", "; cout <<endl;
    // }
    bool isok = true;
    REP(i, blocks.size()) {
      if (!is_valid_tree(i)) {
        isok = false;
        break;
      }
    }
    cout << (isok ? "STABLE" : "UNSTABLE") << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
#define REP(i, j) for (int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for (int i = (int)(j); i < (int)(k); ++i)
#define P pair<int, int>
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
const int MAX_N = 41;

int my[] = {-1, 1, 0, 0};
int mx[] = {0, 0, 1, -1};

class C {
public:
  int cnt, sum, parent;
  double p_xl, p_xr;
  vector<P> cs;
  C(int _p, vector<P> _cs, double _p_xl, double _p_xr) {
    parent = _p;
    cs = _cs;
    cnt = (int)(cs.size());
    sum = 0;
    REP(i, cs.size()) { sum += cs[i].second; }
    p_xl = _p_xl;
    p_xr = _p_xr;
  }
  C(){};
};

int W, H;
string f[MAX_N];
vector<C> blocks;
vector<set<int>> children;

void find_block(int y, int x, char c, vector<P> &v) {
  f[y][x] = '.';
  v.push_back(P(y, x));
  REP(i, 4) {
    int ny = y + my[i], nx = x + mx[i];
    if (ny >= 0 && nx >= 0 && ny < H && nx < W && f[ny][nx] == c)
      find_block(ny, nx, c, v);
  }
}

int find_parent(int now) {
  REP(i, blocks.size()) {
    if (i == now)
      continue;
    REP(j, blocks[now].cs.size()) {
      REP(k, blocks[i].cs.size()) {
        int now_y = blocks[now].cs[j].first;
        int now_x = blocks[now].cs[j].second;
        int block_y = blocks[i].cs[k].first;
        int block_x = blocks[i].cs[k].second;
        if (now_x == block_x && now_y + 1 == block_y) {
          blocks[now].p_xl = 100.0;
          blocks[now].p_xr = -1.0;
          REP(j, blocks[i].cs.size()) {
            if (blocks[i].cs[j].first == block_y) {
              blocks[now].p_xl =
                  min(blocks[now].p_xl, (double)blocks[i].cs[j].second - 0.5);
              blocks[now].p_xr =
                  max(blocks[now].p_xr, (double)blocks[i].cs[j].second + 0.5);
            }
          }
          return i;
        }
      }
    }
  }
  return -1;
}

void find_children(int now, set<int> &c) {
  REP(i, blocks.size()) {
    if (blocks[i].parent == now && c.find(i) == c.end()) {
      c.insert(i);
      find_children(i, c);
    }
  }
}

bool is_valid_tree(int now) {
  int a = blocks[now].sum, b = blocks[now].cnt;
  for (set<int>::iterator it = children[now].begin(); it != children[now].end();
       ++it) {
    C block = blocks[(*it)];
    a += block.sum;
    b += block.cnt;
  }
  double m = (double)a / b;
  // cout <<now <<" : " <<blocks[now].p_xl <<", " <<m <<", " <<blocks[now].p_xr
  // <<endl;
  return (m > blocks[now].p_xl && m < blocks[now].p_xr ? true : false);
}

int main() {
  while (cin >> W >> H && H) {
    blocks = vector<C>();
    REP(i, H) cin >> f[i];
    REP(i, W) {
      if (isdigit(f[H - 1][i])) {
        vector<P> cs;
        find_block(H - 1, i, f[H - 1][i], cs);
        double xl = 100, xr = -1;
        REP(k, cs.size()) {
          if (cs[k].first == H - 1) {
            xl = min(xl, cs[k].second - 0.5);
            xr = max(xl, cs[k].second + 0.5);
          }
        }
        blocks.push_back(C(-1, cs, xl, xr));
      }
    }
    // REP(i, blocks[0].cs.size()) cout <<blocks[0].cs[i].first <<", "
    // <<blocks[0].cs[i].second <<", " <<blocks[0].p_xl <<", " <<blocks[0].p_xr
    // <<endl;
    for (int i = H - 1; i >= 0; --i) {
      for (int j = W - 1; j >= 0; --j) {
        if (isdigit(f[i][j])) {
          vector<P> cs;
          find_block(i, j, f[i][j], cs);
          blocks.push_back(C(-1, cs, -1, 100));
        }
      }
    }
    FOR(i, 1, blocks.size())
    blocks[i].parent = find_parent(i);
    // REP(i, blocks.size()){
    //   cout <<i <<" : " <<endl;
    //   cout <<"parent = " <<blocks[i].parent <<", xl = " <<blocks[i].p_xl <<",
    //   xr = " <<blocks[i].p_xr <<endl; REP(j, blocks[i].cs.size()) cout
    //   <<blocks[i].cs[j].first <<", " <<blocks[i].cs[j].second <<" | "; cout
    //   <<endl;
    // }
    children = vector<set<int>>((int)(blocks.size()));
    FOR(i, 1, blocks.size()) children[0].insert(i);
    FOR(i, 1, blocks.size()) find_children(i, children[i]);
    // REP(i, blocks.size()){
    //   cout <<i <<" : ";
    //   for(set<int>::iterator it = children[i].begin(); it !=
    //   children[i].end(); ++it) cout <<(*it) <<", "; cout <<endl;
    // }
    bool isok = true;
    REP(i, blocks.size()) {
      if (!is_valid_tree(i)) {
        isok = false;
        break;
      }
    }
    cout << (isok ? "STABLE" : "UNSTABLE") << endl;
  }
  return 0;
}