Problem p00749 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
#define eps 1e-8
using namespace std;
typedef complex<double> point;
class piece {
public:
  piece(vector<int> x, vector<int> y, int xr_, int xl_, int id_)
      : xr(xr_), xl(xl_), id(id_) {
    double gx = 0, gy = 0;
    for (int i = 0; i < x.size(); i++) {
      block.push_back(point(x[i], y[i]));
      gx += x[i] + 0.5;
      gy += y[i] + 0.5;
    }
    gravity = point(gx / x.size(), gy / y.size());
  };
  ~piece() {}
  inline void SetSupport(piece p) { support.insert(p); }
  void SetRange(vector<string> &grid);
  inline int GetBlockSize() { return block.size(); }
  inline point GetBlock(int id_) { return block[id_]; }
  inline point GetGrabity() { return gravity; }
  inline set<piece> GetSupport() { return support; }
  inline int GetSupportSize() { return support.size(); }
  inline int GetId() { return id; }
  bool IsBalance() {
    double x = gravity.real() * block.size();
    int block_sum = block.size();
    for (piece i : support) {
      x += i.GetGrabity().real() * i.GetBlockSize();
      block_sum += i.GetBlockSize();
    }
    x /= block_sum;
    return (xl + eps < x && x < xr - eps + 1);
  }

  bool operator<(const piece p) const { return id < p.id; }
  void PrintPiece() {
    std::cout << "id:" << id << std::endl;
    std::cout << "xr:" << xr << " xl:" << xl << std::endl;
    std::cout << "gravity:" << gravity << std::endl;
    for (int i = 0; i < block.size(); i++) {
      std::cout << "block[" << i << "]:" << block[i] << std::endl;
    }
    for (piece i : support) {
      std::cout << "support:" << i.GetId() << std::endl;
    }
    std::cout << std::endl;
  }
  set<piece> support;

private:
  int xr, xl, id;
  point gravity;
  vector<point> block;
};
void piece::SetRange(vector<string> &grid) {
  int h = grid.size();
  for (int i = 0; i < block.size(); i++) {
    int px = block[i].real(), py = block[i].imag();
    if (block[i].imag() == h - 1 ||
        (grid[py + 1][px] != '.' && grid[py + 1][px] != grid[py][px])) {
      xr = max(xr, px);
      xl = min(xl, px);
    }
  }
}
void SetIndirectSupport(vector<piece> &vp, piece &p) {
  if (p.GetSupportSize() == 0)
    return;
  set<piece> p_support = vp[p.GetId()].support;
  for (piece i : p_support) {
    // std::cout << p.GetId() << std::endl;
    // p.PrintPiece();
    SetIndirectSupport(vp, vp[i.GetId()]);
    // set<piece> i_support =
    for (piece j : vp[i.GetId()].support) {
      p.SetSupport(j);
    }
  }
}

bool range(int x, int y, int w, int h) {
  if (0 <= x && x < w && 0 <= y && y < h)
    return true;
  return false;
}

int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
void dfs(vector<string> &grid, vector<int> &x, vector<int> &y, int px, int py,
         char c) {
  int w = grid[0].size(), h = grid.size();
  x.push_back(px);
  y.push_back(py);
  grid[py][px] = '.';
  for (int i = 0; i < 4; i++) {
    if (!range(px + dx[i], py + dy[i], w, h))
      continue;
    if (grid[py + dy[i]][px + dx[i]] == c) {
      dfs(grid, x, y, px + dx[i], py + dy[i], c);
    }
  }
}

void printGrid(vector<string> &grid) {
  for (int i = 0; i < grid.size(); i++) {
    std::cout << grid[i] << std::endl;
  }
  std::cout << std::endl;
}

bool IsSupport(vector<string> &grid, point b) {
  if (b.imag() > 0 && grid[b.imag() - 1][b.real()] != '.' &&
      grid[b.imag() - 1][b.real()] != grid[b.imag()][b.real()])
    return true;
  return false;
}

int main(int argc, char *argv[]) {
  int w, h;
  while (std::cin >> w >> h, w) {
    vector<string> grid(h);
    for (int i = 0; i < h; i++) {
      std::cin >> grid[i];
    }
    vector<piece> p;
    int cnt = 0;
    for (int i = h - 1; i >= 0; i--) {
      for (int j = 0; j < w; j++) {
        if (grid[i][j] != '.') {
          vector<int> x, y;
          int xr, xl;
          dfs(grid, x, y, j, i, grid[i][j]);
          p.push_back(piece(x, y, 0, 1e9, cnt));
          cnt++;
        }
      }
    }
    for (int i = 0; i < p.size(); i++) {
      for (int j = 0; j < p[i].GetBlockSize(); j++) {
        point b = p[i].GetBlock(j);
        grid[(int)b.imag()][(int)b.real()] = '0' + p[i].GetId();
      }
    }
    for (int i = 0; i < p.size(); i++) {
      p[i].SetRange(grid);
    }
    for (int i = 0; i < p.size(); i++) {
      for (int j = 0; j < p[i].GetBlockSize(); j++) {
        point b = p[i].GetBlock(j);
        if (IsSupport(grid, b)) {
          int id = grid[b.imag() - 1][b.real()] - '0';
          p[i].SetSupport(p[id]);
        }
      }
    }
    SetIndirectSupport(p, p[0]);
    // std::cout << w << " " << h << std::endl;
    for (int i = 0; i < p.size(); i++) {
      // p[i].PrintPiece();
      if (!p[i].IsBalance()) {
        std::cout << "UNSTABLE" << std::endl;
        break;
      } else if (i == p.size() - 1) {
        std::cout << "STABLE" << std::endl;
      }
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define eps 1e-8
using namespace std;
typedef complex<double> point;
class piece {
public:
  piece(vector<int> x, vector<int> y, int xr_, int xl_, int id_)
      : xr(xr_), xl(xl_), id(id_) {
    double gx = 0, gy = 0;
    for (int i = 0; i < x.size(); i++) {
      block.push_back(point(x[i], y[i]));
      gx += x[i] + 0.5;
      gy += y[i] + 0.5;
    }
    gravity = point(gx / x.size(), gy / y.size());
  };
  ~piece() {}
  inline void SetSupport(piece p) { support.insert(p); }
  inline void SetRange(vector<string> &grid);
  inline int GetBlockSize() { return block.size(); }
  inline point GetBlock(int id_) { return block[id_]; }
  inline point GetGrabity() { return gravity; }
  inline set<piece> GetSupport() { return support; }
  inline int GetSupportSize() { return support.size(); }
  inline int GetId() { return id; }
  bool IsBalance() {
    double x = gravity.real() * block.size();
    int block_sum = block.size();
    for (piece i : support) {
      x += i.GetGrabity().real() * i.GetBlockSize();
      block_sum += i.GetBlockSize();
    }
    x /= block_sum;
    return (xl + eps < x && x < xr - eps + 1);
  }

  bool operator<(const piece p) const { return id < p.id; }
  void PrintPiece() {
    std::cout << "id:" << id << std::endl;
    std::cout << "xr:" << xr << " xl:" << xl << std::endl;
    std::cout << "gravity:" << gravity << std::endl;
    for (int i = 0; i < block.size(); i++) {
      std::cout << "block[" << i << "]:" << block[i] << std::endl;
    }
    for (piece i : support) {
      std::cout << "support:" << i.GetId() << std::endl;
    }
    std::cout << std::endl;
  }

private:
  int xr, xl, id;
  point gravity;
  vector<point> block;
  set<piece> support;
};
void piece::SetRange(vector<string> &grid) {
  int h = grid.size();
  for (int i = 0; i < block.size(); i++) {
    int px = block[i].real(), py = block[i].imag();
    if (block[i].imag() == h - 1 ||
        (grid[py + 1][px] != '.' && grid[py + 1][px] != grid[py][px])) {
      xr = max(xr, px);
      xl = min(xl, px);
    }
  }
}
void SetIndirectSupport(vector<piece> &vp, piece &p) {
  if (p.GetSupportSize() == 0)
    return;
  set<piece> p_support = vp[p.GetId()].GetSupport();
  for (piece i : p_support) {
    SetIndirectSupport(vp, vp[i.GetId()]);
    set<piece> i_support = vp[i.GetId()].GetSupport();
    for (piece j : i_support) {
      p.SetSupport(j);
    }
  }
}

bool range(int x, int y, int w, int h) {
  if (0 <= x && x < w && 0 <= y && y < h)
    return true;
  return false;
}

int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
void dfs(vector<string> &grid, vector<int> &x, vector<int> &y, int px, int py,
         char c) {
  int w = grid[0].size(), h = grid.size();
  x.push_back(px);
  y.push_back(py);
  grid[py][px] = '.';
  for (int i = 0; i < 4; i++) {
    if (!range(px + dx[i], py + dy[i], w, h))
      continue;
    if (grid[py + dy[i]][px + dx[i]] == c) {
      dfs(grid, x, y, px + dx[i], py + dy[i], c);
    }
  }
}

void printGrid(vector<string> &grid) {
  for (int i = 0; i < grid.size(); i++) {
    std::cout << grid[i] << std::endl;
  }
  std::cout << std::endl;
}

bool IsSupport(vector<string> &grid, point b) {
  if (b.imag() > 0 && grid[b.imag() - 1][b.real()] != '.' &&
      grid[b.imag() - 1][b.real()] != grid[b.imag()][b.real()])
    return true;
  return false;
}

int main(int argc, char *argv[]) {
  int w, h;
  while (std::cin >> w >> h, w) {
    vector<string> grid(h);
    for (int i = 0; i < h; i++) {
      std::cin >> grid[i];
    }
    vector<piece> p;
    int cnt = 0;
    for (int i = h - 1; i >= 0; i--) {
      for (int j = 0; j < w; j++) {
        if (grid[i][j] != '.') {
          vector<int> x, y;
          int xr, xl;
          dfs(grid, x, y, j, i, grid[i][j]);
          p.push_back(piece(x, y, 0, 1e9, cnt));
          cnt++;
        }
      }
    }
    for (int i = 0; i < p.size(); i++) {
      for (int j = 0; j < p[i].GetBlockSize(); j++) {
        point b = p[i].GetBlock(j);
        grid[(int)b.imag()][(int)b.real()] = '0' + p[i].GetId();
      }
    }
    for (int i = 0; i < p.size(); i++) {
      p[i].SetRange(grid);
    }
    for (int i = 0; i < p.size(); i++) {
      for (int j = 0; j < p[i].GetBlockSize(); j++) {
        point b = p[i].GetBlock(j);
        if (IsSupport(grid, b)) {
          int id = grid[b.imag() - 1][b.real()] - '0';
          p[i].SetSupport(p[id]);
        }
      }
    }
    for (int i = 0; i < p.size(); i++) {
      SetIndirectSupport(p, p[i]);
    }
    for (int i = 0; i < p.size(); i++) {
      if (!p[i].IsBalance()) {
        std::cout << "UNSTABLE" << std::endl;
        break;
      } else if (i == p.size() - 1) {
        std::cout << "STABLE" << std::endl;
      }
    }
  }
  return 0;
}