Problem p02579 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <ctype.h>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define REP(i, n) for (ll i = 0; i < (ll)(n); ++i)
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

int w_par[10000];
int w_rank[10000];

void w_init(int n) {
  REP(i, n) {
    w_par[i] = i;
    w_rank[i] = 0;
  }
}
int w_find(int x) {
  if (w_par[x] == x) {
    return x;
  } else {
    return w_par[x] = w_find(w_par[x]);
  }
}
void w_unite(int x, int y) {
  x = w_find(x);
  y = w_find(y);
  if (x == y)
    return;
  if (w_rank[x] < w_rank[y]) {
    w_par[x] = y;
  } else {
    w_par[y] = x;
    if (w_rank[x] == w_rank[y])
      w_rank[x]++;
  }
}

int main() {
  int H, W;
  cin >> H >> W;
  int c[2], d[2];
  cin >> c[0] >> c[1];
  c[0]--;
  c[1]--;
  cin >> d[0] >> d[1];
  d[0]--;
  d[1]--;
  vector<string> s(H);
  REP(i, H) cin >> s[i];

  vector<bool> isway(H * W, true);
  w_init(H * W);
  REP(i, H) {
    REP(j, W) {
      if (s[i][j] == '#') {
        isway[i * W + j] = false;
        continue;
      }
      if (i != 0 && s[i - 1][j] == '.')
        w_unite(i * W + j, (i - 1) * W + j);
      if (i != H - 1 && s[i + 1][j] == '.')
        w_unite(i * W + j, (i + 1) * W + j);
      if (j != 0 && s[i][j - 1] == '.')
        w_unite(i * W + j, i * W + j - 1);
      if (j != W - 1 && s[i][j + 1] == '.')
        w_unite(i * W + j, i * W + j + 1);
    }
  }

  if (w_find(c[0] * W + c[1]) == w_find(d[0] * W + d[1])) {
    cout << 0 << endl;
    return 0;
  }

  map<int, set<int>> g;

  REP(i, H) {
    REP(j, W) {
      if (!isway[i * W + j])
        continue;
      for (int k = -2; k <= 2; k++) {
        if (i + k < 0 || i + k >= H)
          continue;
        for (int l = -2; l <= 2; l++) {
          if (j + l < 0 || j + l >= W)
            continue;
          int now = (i + k) * W + j + l;
          if (!isway[now])
            continue;
          if (w_find(i * W + j) == w_find(now))
            continue;

          g[w_find(i * W + j)].insert(w_find(now));
          g[w_find(now)].insert(w_find(i * W + j));
        }
      }
    }
  }

  int start = w_find(c[0] * W + c[1]);
  int goal = w_find(d[0] * W + d[1]);
  map<int, int> count;
  queue<int> q;
  q.push(start);
  count[start] = 0;
  while (!q.empty()) {
    int now = q.front();
    q.pop();

    for (auto x : g[now]) {
      if (count[x] != 0)
        continue;
      if (x == goal) {
        cout << count[now] + 1 << endl;
        return 0;
      }
      count[x] = count[now] + 1;
      q.push(x);
    }
  }

  cout << -1 << endl;

  return 0;
}

Fixed submission:
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <ctype.h>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define REP(i, n) for (ll i = 0; i < (ll)(n); ++i)
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

int w_par[1000000];
int w_rank[1000000];

void w_init(int n) {
  REP(i, n) {
    w_par[i] = i;
    w_rank[i] = 0;
  }
}
int w_find(int x) {
  if (w_par[x] == x) {
    return x;
  } else {
    return w_par[x] = w_find(w_par[x]);
  }
}
void w_unite(int x, int y) {
  x = w_find(x);
  y = w_find(y);
  if (x == y)
    return;
  if (w_rank[x] < w_rank[y]) {
    w_par[x] = y;
  } else {
    w_par[y] = x;
    if (w_rank[x] == w_rank[y])
      w_rank[x]++;
  }
}

int main() {
  int H, W;
  cin >> H >> W;
  int c[2], d[2];
  cin >> c[0] >> c[1];
  c[0]--;
  c[1]--;
  cin >> d[0] >> d[1];
  d[0]--;
  d[1]--;
  vector<string> s(H);
  REP(i, H) cin >> s[i];

  vector<bool> isway(H * W, true);
  w_init(H * W);
  REP(i, H) {
    REP(j, W) {
      if (s[i][j] == '#') {
        isway[i * W + j] = false;
        continue;
      }
      if (i != 0 && s[i - 1][j] == '.')
        w_unite(i * W + j, (i - 1) * W + j);
      if (i != H - 1 && s[i + 1][j] == '.')
        w_unite(i * W + j, (i + 1) * W + j);
      if (j != 0 && s[i][j - 1] == '.')
        w_unite(i * W + j, i * W + j - 1);
      if (j != W - 1 && s[i][j + 1] == '.')
        w_unite(i * W + j, i * W + j + 1);
    }
  }

  if (w_find(c[0] * W + c[1]) == w_find(d[0] * W + d[1])) {
    cout << 0 << endl;
    return 0;
  }

  map<int, set<int>> g;

  REP(i, H) {
    REP(j, W) {
      if (!isway[i * W + j])
        continue;
      for (int k = -2; k <= 2; k++) {
        if (i + k < 0 || i + k >= H)
          continue;
        for (int l = -2; l <= 2; l++) {
          if (j + l < 0 || j + l >= W)
            continue;
          int now = (i + k) * W + j + l;
          if (!isway[now])
            continue;
          if (w_find(i * W + j) == w_find(now))
            continue;

          g[w_find(i * W + j)].insert(w_find(now));
          g[w_find(now)].insert(w_find(i * W + j));
        }
      }
    }
  }

  int start = w_find(c[0] * W + c[1]);
  int goal = w_find(d[0] * W + d[1]);
  map<int, int> count;
  queue<int> q;
  q.push(start);
  count[start] = 0;
  while (!q.empty()) {
    int now = q.front();
    q.pop();

    for (auto x : g[now]) {
      if (count[x] != 0)
        continue;
      if (x == goal) {
        cout << count[now] + 1 << endl;
        return 0;
      }
      count[x] = count[now] + 1;
      q.push(x);
    }
  }

  cout << -1 << endl;

  return 0;
}