Problem p00937 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;
// Brute Force Attack!
int main(int argc, char *argv[]) {
  int n, m, a, b, c;
  cin >> n >> m >> a >> b >> c;
  vector<int> abc = {a, b, c};
  sort(abc.begin(), abc.end());
  vector<vector<bool>> step(n, vector<bool>(n, false));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    step[u - 1][v - 1] = true;
  }
  a = abc[0];
  b = abc[1];
  c = abc[2];
  vector<vector<bool>> arch(n, vector<bool>(n));
  vector<vector<bool>> brch(n, vector<bool>(n));
  vector<vector<bool>> crch(n, vector<bool>(n));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      arch[i][j] = i == j;
      brch[i][j] = i == j;
      crch[i][j] = i == j;
    }
  }
  auto mul = [](int n, vector<vector<bool>> &z, vector<vector<bool>> &y) {
    bool t[n][n];
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        bool c = false;
        for (int k = 0; k < n; k++) {
          c = c || (z[i][k] && y[k][j]);
        }
        t[i][j] = c;
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        z[i][j] = t[i][j];
      }
    }
  };
  // c is the biggest
  while (c != 0) {
    if (a & 1) { // arch *= step
      mul(n, arch, step);
    }
    if (b & 1) { // brch *= step
      mul(n, brch, step);
    }
    if (c & 1) { // crch *= step
      mul(n, crch, step);
    }
    mul(n, step, step);
    a >>= 1;
    b >>= 1;
    c >>= 1;
  }

  // arch: a-step reachable
  // brch: b-step reachable
  // crch: c-step reachable

  vector<int> ok(n, -1);
  ok[n - 1] = 0; // the goal is ok

  auto reachable = [&ok, &n](const vector<vector<bool>> &rch, int i) {
    for (int j = 0; j < n; j++) {
      if (rch[i][j] && (ok[j] >= 0))
        return true;
    }
    return false;
  };

  auto search = [&]() {
    bool done = false;
    int ss = 0;
    while (!done) {
      ss++;
      done = true;
      vector<int> ok2(n, -1);
      for (int i = 0; i < n; i++) {
        // if i has a-reachable ok, b-reachable ok, and c-reachable ok vertives,
        // then i is also ok
        if (ok[i] < 0 && reachable(arch, i) && reachable(brch, i) &&
            reachable(crch, i)) {
          ok2[i] = ss;
          if (i == 0) {
            ok[i] = ok2[i];
            return;
          }
          done = false;
        }
      }
      for (int i = 0; i < n; i++) {
        ok[i] = ok2[i];
      }
    }
  };
  search();
  if (ok[0] < 0)
    cout << "IMPOSSIBLE" << endl;
  else
    cout << ok[0] << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;
// Brute Force Attack!
int main(int argc, char *argv[]) {
  int n, m, a, b, c;
  cin >> n >> m >> a >> b >> c;
  vector<int> abc = {a, b, c};
  sort(abc.begin(), abc.end());
  vector<vector<bool>> step(n, vector<bool>(n, false));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    step[u - 1][v - 1] = true;
  }
  a = abc[0];
  b = abc[1];
  c = abc[2];
  vector<vector<bool>> arch(n, vector<bool>(n));
  vector<vector<bool>> brch(n, vector<bool>(n));
  vector<vector<bool>> crch(n, vector<bool>(n));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      arch[i][j] = i == j;
      brch[i][j] = i == j;
      crch[i][j] = i == j;
    }
  }
  auto mul = [](int n, vector<vector<bool>> &z, vector<vector<bool>> &y) {
    bool t[n][n];
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        bool c = false;
        for (int k = 0; k < n; k++) {
          c = c || (z[i][k] && y[k][j]);
        }
        t[i][j] = c;
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        z[i][j] = t[i][j];
      }
    }
  };
  // c is the biggest
  while (c != 0) {
    if (a & 1) { // arch *= step
      mul(n, arch, step);
    }
    if (b & 1) { // brch *= step
      mul(n, brch, step);
    }
    if (c & 1) { // crch *= step
      mul(n, crch, step);
    }
    mul(n, step, step);
    a >>= 1;
    b >>= 1;
    c >>= 1;
  }

  // arch: a-step reachable
  // brch: b-step reachable
  // crch: c-step reachable

  vector<int> ok(n, -1);
  ok[n - 1] = 0; // the goal is ok

  auto reachable = [&ok, &n](const vector<vector<bool>> &rch, int i) {
    for (int j = 0; j < n; j++) {
      if (rch[i][j] && (ok[j] >= 0))
        return true;
    }
    return false;
  };

  auto search = [&]() {
    bool done = false;
    int ss = 0;
    while (!done) {
      ss++;
      done = true;
      vector<int> ok2(n, -1);
      for (int i = 0; i < n; i++) {
        // if i has a-reachable ok, b-reachable ok, and c-reachable ok vertives,
        // then i is also ok
        if (ok[i] < 0 && reachable(arch, i) && reachable(brch, i) &&
            reachable(crch, i)) {
          ok2[i] = ss;
          if (i == 0) {
            ok[i] = ok2[i];
            return;
          }
          done = false;
        }
      }
      for (int i = 0; i < n; i++) {
        ok[i] = ok2[i] >= 0 ? ok2[i] : ok[i];
      }
    }
  };
  search();
  if (ok[0] < 0)
    cout << "IMPOSSIBLE" << endl;
  else
    cout << ok[0] << endl;
  return 0;
}