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

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iostream>
#include <map>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; ++i)
#define rep(i, n) REP(i, 0, n)

using namespace std;

int dx[] = {0, 1};
int dy[] = {1, 0};

struct Data {
  int x, y;
  char v;
  bool operator<(const Data &data) const {
    if (x != data.x)
      return x < data.x;
    if (y != data.y)
      return y < data.y;
    return v < data.v;
  }
};

bool used[60][60];
void makeGraph(vector<string> &C, vector<vector<int>> &G, vector<char> &ws) {
  int H = C.size(), W = C[0].size();
  map<Data, int> mp;
  int _cnt = 0;
  rep(i, H) rep(j, W) if ((i == 0 && j == 0) || (i == H - 1 && j == W - 1) ||
                          isalpha(C[i][j])) {
    mp[(Data){j, i, C[i][j]}] = _cnt++;
  }
  int V = mp.size();
  G.resize(V);
  rep(i, V) G[i].clear();
  ws.resize(V);

  rep(i, H) rep(j, W) if ((i == 0 && j == 0) || (i == H - 1 && j == W - 1) ||
                          isalpha(C[i][j])) {
    int sp = mp[(Data){j, i, C[i][j]}];
    ws[sp] = C[i][j];
    memset(used, false, sizeof used);
    deque<int> deq;
    deq.push_back(j + i * W);

    while (!deq.empty()) {
      int cur = deq.front();
      deq.pop_front();
      int x = cur % W, y = cur / W;
      rep(k, 2) {
        int nx = x + dx[k], ny = y + dy[k];

        if (!(0 <= nx && nx < W && 0 <= ny && ny < H))
          continue;
        if (used[ny][nx])
          continue;
        if (C[ny][nx] == '#')
          continue;

        used[ny][nx] = true;
        if (isalpha(C[ny][nx]) || (nx == W - 1 && ny == H - 1))
          G[sp].push_back(mp[(Data){nx, ny, C[ny][nx]}]);
        deq.push_back(nx + ny * W);
      }
    }
  }
}

bool visit(const vector<vector<int>> &G, int v, vector<int> &order,
           vector<int> &color) {
  color[v] = 1;
  rep(i, (int)G[v].size()) {
    int e = G[v][i];
    if (color[e] == 2)
      continue;
    if (color[e] == 1)
      return false;
    if (!visit(G, e, order, color))
      return false;
  }
  order.push_back(v);
  color[v] = 2;
  return true;
}

bool topologicalSort(const vector<vector<int>> &G, vector<int> &order) {
  int SizeG = G.size();
  vector<int> color(SizeG);
  for (int u = 0; u < SizeG; u++)
    if (!color[u] && !visit(G, u, order, color))
      return false;
  reverse(order.begin(), order.end());
  return true;
}

bool canPut(char a, char A) {
  if (!islower(a) || !isupper(A))
    return false;
  return toupper(a) == A;
}

#define MAX_V 600
bool hasEdge[MAX_V][MAX_V];
int dp[MAX_V][MAX_V];
void compute(vector<string> &C) {
  if (C.size() == 1 && C[0].size() == 1) {
    puts("0");
    return;
  }
  // DAG???
  vector<vector<int>> G;
  vector<char> ws;
  makeGraph(C, G, ws);

  {
    bool fin = true;
    rep(i, (int)G[0].size()) if (G[0][i] == (int)G.size() - 1) {
      fin = false;
      break;
    }
    if (fin) {
      puts("-1");
      return;
    }
  }

  // topological sort
  vector<int> order;
  assert(topologicalSort(G, order));

  // DP
  int V = G.size();

  memset(hasEdge, false, sizeof hasEdge);
  rep(i, V) rep(j, (int)G[i].size()) hasEdge[i][G[i][j]] = true;
  assert(V < MAX_V);
  memset(dp, 0, sizeof dp);
  REP(len, 2, V + 1) {
    rep(i, V) {
      int j = i + len - 1;
      if (j >= V)
        break;
      int sp = order[i];
      int ep = order[j];
      if (!hasEdge[sp][ep])
        continue;

      bool put = false;
      if (canPut(ws[sp], ws[ep])) {
        put = true;
        dp[sp][ep] = max(dp[sp][ep], 1);
      }

      rep(k, (int)G[sp].size()) {
        int nex = G[sp][k];
        rep(l, (int)G[nex].size()) {
          int nnex = G[nex][l];
          if (!(nnex == ep || hasEdge[nnex][ep]))
            continue;
          dp[sp][ep] =
              max(dp[sp][ep], max(dp[nex][nnex], dp[sp][nex] + dp[nnex][ep]));
          if (put && nnex != ep) {
            dp[sp][ep] = max(dp[sp][ep], dp[nex][nnex] + 1);
          }
        }
      }
    }
  }
  cout << dp[0][V - 1] << endl;
}

int main() {
  int H, W;
  while (cin >> H >> W, H | W) {
    vector<string> C(H);
    rep(i, H) cin >> C[i];
    compute(C);
  }
  return 0;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; ++i)
#define rep(i, n) REP(i, 0, n)

using namespace std;

int dx[] = {0, 1};
int dy[] = {1, 0};

struct Data {
  int x, y;
  char v;
  bool operator<(const Data &data) const {
    if (x != data.x)
      return x < data.x;
    if (y != data.y)
      return y < data.y;
    return v < data.v;
  }
};

bool used[60][60];
void makeGraph(vector<string> &C, vector<vector<int>> &G, vector<char> &ws) {
  int H = C.size(), W = C[0].size();
  map<Data, int> mp;
  rep(i, H) rep(j, W) if ((i == 0 && j == 0) || (i == H - 1 && j == W - 1) ||
                          isalpha(C[i][j])) {
    mp[(Data){j, i, C[i][j]}] = (int)mp.size();
  }
  int V = mp.size();
  G.resize(V);
  ws.resize(V);

  rep(i, H) rep(j, W) if ((i == 0 && j == 0) || (i == H - 1 && j == W - 1) ||
                          isalpha(C[i][j])) {
    int sp = mp[(Data){j, i, C[i][j]}];
    ws[sp] = C[i][j];
    memset(used, false, sizeof used);
    deque<int> deq;
    deq.push_back(j + i * W);

    while (!deq.empty()) {
      int cur = deq.front();
      deq.pop_front();
      int x = cur % W, y = cur / W;
      rep(k, 2) {
        int nx = x + dx[k], ny = y + dy[k];

        if (!(0 <= nx && nx < W && 0 <= ny && ny < H))
          continue;
        if (used[ny][nx])
          continue;
        if (C[ny][nx] == '#')
          continue;

        used[ny][nx] = true;
        if (isalpha(C[ny][nx]) || (nx == W - 1 && ny == H - 1))
          G[sp].push_back(mp[(Data){nx, ny, C[ny][nx]}]);
        deq.push_back(nx + ny * W);
      }
    }
  }
}

bool visit(const vector<vector<int>> &G, int v, vector<int> &order,
           vector<int> &color) {
  color[v] = 1;
  rep(i, (int)G[v].size()) {
    int e = G[v][i];
    if (color[e] == 2)
      continue;
    if (color[e] == 1)
      return false;
    if (!visit(G, e, order, color))
      return false;
  }
  order.push_back(v);
  color[v] = 2;
  return true;
}

bool topologicalSort(const vector<vector<int>> &G, vector<int> &order) {
  int SizeG = G.size();
  vector<int> color(SizeG);
  for (int u = 0; u < SizeG; u++)
    if (!color[u] && !visit(G, u, order, color))
      return false;
  reverse(order.begin(), order.end());
  return true;
}

bool canPut(char a, char A) {
  if (!islower(a) || !isupper(A))
    return false;
  return toupper(a) == A;
}

#define MAX_V 600
bool hasEdge[MAX_V][MAX_V];
int dp[MAX_V][MAX_V];
void compute(vector<string> &C) {
  if (C.size() == 1 && C[0].size() == 1) {
    puts("0");
    return;
  }
  // DAG???
  vector<vector<int>> G;
  vector<char> ws;
  makeGraph(C, G, ws);

  {
    bool fin = true;
    rep(i, (int)G[0].size()) if (G[0][i] == (int)G.size() - 1) {
      fin = false;
      break;
    }
    if (fin) {
      puts("-1");
      return;
    }
  }

  // topological sort
  vector<int> order;
  assert(topologicalSort(G, order));

  // DP
  int V = G.size();

  memset(hasEdge, false, sizeof hasEdge);
  rep(i, V) rep(j, (int)G[i].size()) hasEdge[i][G[i][j]] = true;
  assert(V < MAX_V);
  memset(dp, 0, sizeof dp);
  REP(len, 2, V + 1) {
    rep(i, V) {
      int j = i + len - 1;
      if (j >= V)
        break;
      int sp = order[i];
      int ep = order[j];
      if (!hasEdge[sp][ep])
        continue;

      bool put = false;
      if (canPut(ws[sp], ws[ep])) {
        put = true;
        dp[sp][ep] = max(dp[sp][ep], 1);
      }

      rep(k, (int)G[sp].size()) {
        int nex = G[sp][k];
        rep(l, (int)G[nex].size()) {
          int nnex = G[nex][l];
          if (!(nnex == ep || hasEdge[nnex][ep]))
            continue;
          dp[sp][ep] =
              max(dp[sp][ep], max(dp[nex][nnex], dp[sp][nex] + dp[nnex][ep]));
          if (put && nnex != ep) {
            dp[sp][ep] = max(dp[sp][ep], dp[nex][nnex] + 1);
          }
        }
      }
    }
  }
  cout << dp[0][V - 1] << endl;
}

int main() {
  int H, W;
  while (cin >> H >> W, H | W) {
    vector<string> C(H);
    rep(i, H) cin >> C[i];
    compute(C);
  }
  return 0;
}