Problem p03157 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i, x) for (long long i = 0; i < x; i++)
#define repn(i, x) for (long long i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
vector<pair<string, P>> vec;

// Union-Find

#define MAX_N 20001

long long par[MAX_N];    // 親
long long rankuf[MAX_N]; // 木の深さ
// n要素で初期化
void init(long long n) {
  for (long long i = 0; i < n; i++) {
    par[i] = i;
    rankuf[i] = 0;
  }
}
// 木の根を求める
long long find(long long x) {
  if (par[x] == x) {
    return x;
  } else {
    return par[x] = find(par[x]);
  }
}
// xとyの属する集合を併合
void unite(long long x, long long y) {
  x = find(x);
  y = find(y);
  if (x == y)
    return;
  if (rankuf[x] < rankuf[y]) {
    par[x] = y;
  } else {
    par[y] = x;
    if (rankuf[x] == rankuf[y])
      rankuf[x]++;
  }
}
// xとyが同じ集合に属するか否か
bool same(long long x, long long y) { return find(x) == find(y); }

int main() {
  long long W;
  long long H;
  scanf("%lld", &H);
  vector<string> S(H - 1 + 1);
  scanf("%lld", &W);
  for (int i = 0; i <= H - 1; i++) {
    cin >> S[i];
  }
  init(H * W);
  rep(i, H) {
    rep(j, W) {
      if (i - 1 >= 0 && S[i][j] != S[i - 1][j])
        unite(i * W + j, (i - 1) * W + j);
      if (i + 1 < H && S[i][j] != S[i + 1][j])
        unite(i * W + j, (i + 1) * W + j);
      if (j - 1 >= 0 && S[i][j] != S[i][j - 1])
        unite(i * W + j, i * W + j - 1);
      if (j + 1 < W && S[i][j] != S[i][j + 1])
        unite(i * W + j, i * W + j + 1);
    }
  }

  vector<ll> b(H * W), w(H * W);
  rep(i, H) {
    rep(j, W) {
      if (S[i][j] == '#')
        b[find(i * W + j)]++;
      else
        w[find(i * W + j)]++;
    }
  }

  ll res = 0;
  rep(i, H * W) { res += b[i] * w[i]; }

  cout << res << endl;

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i, x) for (long long i = 0; i < x; i++)
#define repn(i, x) for (long long i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
vector<pair<string, P>> vec;

// Union-Find

#define MAX_N 200001

long long par[MAX_N];    // 親
long long rankuf[MAX_N]; // 木の深さ
// n要素で初期化
void init(long long n) {
  for (long long i = 0; i < n; i++) {
    par[i] = i;
    rankuf[i] = 0;
  }
}
// 木の根を求める
long long find(long long x) {
  if (par[x] == x) {
    return x;
  } else {
    return par[x] = find(par[x]);
  }
}
// xとyの属する集合を併合
void unite(long long x, long long y) {
  x = find(x);
  y = find(y);
  if (x == y)
    return;
  if (rankuf[x] < rankuf[y]) {
    par[x] = y;
  } else {
    par[y] = x;
    if (rankuf[x] == rankuf[y])
      rankuf[x]++;
  }
}
// xとyが同じ集合に属するか否か
bool same(long long x, long long y) { return find(x) == find(y); }

int main() {
  long long W;
  long long H;
  scanf("%lld", &H);
  vector<string> S(H - 1 + 1);
  scanf("%lld", &W);
  for (int i = 0; i <= H - 1; i++) {
    cin >> S[i];
  }
  init(H * W);
  rep(i, H) {
    rep(j, W) {
      if (i - 1 >= 0 && S[i][j] != S[i - 1][j])
        unite(i * W + j, (i - 1) * W + j);
      if (i + 1 < H && S[i][j] != S[i + 1][j])
        unite(i * W + j, (i + 1) * W + j);
      if (j - 1 >= 0 && S[i][j] != S[i][j - 1])
        unite(i * W + j, i * W + j - 1);
      if (j + 1 < W && S[i][j] != S[i][j + 1])
        unite(i * W + j, i * W + j + 1);
    }
  }

  vector<ll> b(H * W), w(H * W);
  rep(i, H) {
    rep(j, W) {
      if (S[i][j] == '#')
        b[find(i * W + j)]++;
      else
        w[find(i * W + j)]++;
    }
  }

  ll res = 0;
  rep(i, H * W) { res += b[i] * w[i]; }

  cout << res << endl;

  return 0;
}