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

#include <bits/stdc++.h>

#define each(i, c) for (auto &i : c)
#define unless(cond) if (!(cond))

using namespace std;

typedef long long int lli;
typedef unsigned long long ull;
typedef complex<double> point;

template <typename P, typename Q>
ostream &operator<<(ostream &os, pair<P, Q> p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}

const int inf = 1 << 28;
const int N = 52;
const int M = N * N;

struct Mat {
  Mat() { fill(&val[0][0], &val[N - 1][N - 1] + 1, 0); }
  int val[N][N];
};

Mat operator*(Mat a, Mat b) {
  Mat c;
  for (int i = 0; i < N; ++i) {
    for (int k = 0; k < N; ++k) {
      for (int j = 0; j < N; ++j) {
        c.val[i][j] += a.val[i][k] * b.val[k][j];
        c.val[i][j] = min(c.val[i][j], 1);
      }
    }
  }
  return c;
}

Mat e;

Mat pow(Mat m, int p) {
  if (p == 0)
    return e;
  if (p == 1)
    return m;
  Mat tmp = pow(m, p / 2);
  return p % 2 ? tmp * tmp * m : tmp * tmp;
}

Mat mat_a;
Mat mat_b;
Mat mat_c;

int memo[N][M];
int n, m, a, b, c;
int rec(int curr, int step) {
  unless(step < M) return inf;
  int &ret = memo[curr][step];
  if (ret != -1)
    return ret;
  if (curr == n - 1)
    return step;
  int mn_a = inf;
  int mn_b = inf;
  int mn_c = inf;
  for (int next = 0; next < N; ++next) {
    if (mat_a.val[curr][next])
      mn_a = min(mn_a, rec(next, step + 1));
    if (mat_b.val[curr][next])
      mn_b = min(mn_b, rec(next, step + 1));
    if (mat_c.val[curr][next])
      mn_c = min(mn_c, rec(next, step + 1));
  }
  return ret = max({mn_a, mn_b, mn_c});
}

int main(int argc, char *argv[]) {
  for (int i = 0; i < N; ++i) {
    e.val[i][i] = 1;
  }
  while (cin >> n >> m >> a >> b >> c) {
    Mat in;
    for (int i = 0; i < m; ++i) {
      int src, dst;
      cin >> src >> dst;
      --src;
      --dst;
      in.val[src][dst] = 1;
    }
    mat_a = pow(in, a);
    mat_b = pow(in, b);
    mat_c = pow(in, c);

    // cout << "A" << endl;
    // for (int i = 0; i < n; ++i) {
    //   for (int j = 0; j < n; ++j) cout << mat_a.val[i][j] << ' ' ; cout <<
    //   endl;
    // }
    // cout << "B" << endl;
    // for (int i = 0; i < n; ++i) {
    //   for (int j = 0; j < n; ++j) cout << mat_b.val[i][j] << ' ' ; cout <<
    //   endl;
    // }
    // cout << "C" << endl;
    // for (int i = 0; i < n; ++i) {
    //   for (int j = 0; j < n; ++j) cout << mat_c.val[i][j] << ' ' ; cout <<
    //   endl;
    // }

    fill(&memo[0][0], &memo[N - 1][M - 1] + 1, -1);
    const int dist = rec(0, 0);
    if (dist < inf)
      cout << dist << endl;
    else
      cout << "IMPOSSIBLE" << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define each(i, c) for (auto &i : c)
#define unless(cond) if (!(cond))

using namespace std;

typedef long long int lli;
typedef unsigned long long ull;
typedef complex<double> point;

template <typename P, typename Q>
ostream &operator<<(ostream &os, pair<P, Q> p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}

const int inf = 1 << 28;
const int N = 55;
const int M = N * N * 5;

int g[N][N];
int memo[N][M];
int n, m, a, b, c;
int rec(int curr, int step) {
  unless(step < M) return inf;
  int &ret = memo[curr][step];
  if (ret != -1)
    return ret;
  if (curr == n - 1)
    return step;
  int mn_a = inf;
  int mn_b = inf;
  int mn_c = inf;
  for (int next = 0; next < N; ++next) {
    for (int in = 0; in < N; ++in) {
      if (g[curr][in] + g[in][next] == a) {
        mn_a = min(mn_a, rec(next, step + 1));
      }
      if (g[curr][in] + g[in][next] == b) {
        mn_b = min(mn_b, rec(next, step + 1));
      }
      if (g[curr][in] + g[in][next] == c) {
        mn_c = min(mn_c, rec(next, step + 1));
      }
    }
  }
  return ret = max({mn_a, mn_b, mn_c});
}

int main(int argc, char *argv[]) {
  while (cin >> n >> m >> a >> b >> c) {
    fill(&g[0][0], &g[N - 1][N - 1] + 1, inf);
    for (int i = 0; i < N; ++i) {
      g[i][i] = 0;
    }
    for (int i = 0; i < m; ++i) {
      int src, dst;
      cin >> src >> dst;
      --src;
      --dst;
      g[src][dst] = 1;
    }
    for (int k = 0; k < N; ++k) {
      for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
          g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
        }
      }
    }
    fill(&memo[0][0], &memo[N - 1][M - 1] + 1, -1);
    const int dist = rec(0, 0);
    if (dist < inf)
      cout << dist << endl;
    else
      cout << "IMPOSSIBLE" << endl;
  }
  return 0;
}