Problem p01717 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef int ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/

typedef int Weight;
struct Edge {
  int from, to;
  Weight cost;
  bool operator<(const Edge &e) const { return cost < e.cost; }
  bool operator>(const Edge &e) const { return cost > e.cost; }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
void add_edge(Graph &g, int from, int to, Weight cost) {
  g[from].push_back(Edge{from, to, cost});
}

int n, m, k, sz;
vector<vi> value;

ll dp[2222][2222];
ll solve(int i, int used) {
  if (i == sz) {
    if (used < k)
      return -INF + 1;
    else
      return 0;
  }
  if (dp[i][used] > -INF)
    return dp[i][used];
  ll res = -INF;
  REP(j, value[i].size()) {
    if (used + j > k)
      break;
    chmax(res, solve(i + 1, used + j) + value[i][j]);
  }
  return dp[i][used] = res;
}

int line_memo[2222][2222][2];

vi calc_line(vi &v) {
  int V = v.size() + 1;
  if (v.size() == 0) {
    return vi{0, 0};
  }
  REP(i, V) REP(j, V + 1) REP(k, 2) line_memo[i][j][k] = -INF;
  vi res(V + 1, -INF);
  line_memo[0][0][0] = line_memo[0][1][1] = 0;
  REP(i, V - 1) REP(j, V + 1) {
    chmax(line_memo[i + 1][j][0], max(line_memo[i][j][0], line_memo[i][j][1]));
    if (j < V + 1 - 1)
      chmax(line_memo[i + 1][j + 1][1], line_memo[i][j][0]);
    if (j < V + 1 - 1 && v[i] != 0)
      chmax(line_memo[i + 1][j + 1][1], line_memo[i][j][1] + v[i]);
  }
  res[0] = 0;
  REP(i, res.size()) { REP(j, V) REP(k, 2) chmax(res[i], line_memo[j][i][k]); }
  return res;
}

int loop_memo[2222][2222][2][2];

vi calc_loop(vi &v) {
  int V = v.size();
  REP(i, V + 2) REP(j, V + 2) REP(k, 2) REP(l, 2) loop_memo[i][j][k][l] = -INF;
  vi res(V + 1, -INF);
  loop_memo[0][0][0][0] = loop_memo[0][1][1][1] = 0;
  REP(i, V - 2) REP(j, V + 1) REP(k, 2) {
    chmax(loop_memo[i + 1][j][k][0],
          max(loop_memo[i][j][k][0], loop_memo[i][j][k][1]));
    if (j < V)
      chmax(loop_memo[i + 1][j + 1][k][1], loop_memo[i][j][k][0]);
    if (j < V && v[i] != 0)
      chmax(loop_memo[i + 1][j + 1][k][1], loop_memo[i][j][k][1] + v[i]);
  }

  REP(j, V + 1) {
    REP(k, 2) {
      chmax(loop_memo[V - 1][j][k][0],
            max(loop_memo[V - 2][j][k][0], loop_memo[V - 2][j][k][1]));
      if (k == 0) {
        if (j < V)
          chmax(loop_memo[V - 1][j + 1][k][1], loop_memo[V - 2][j][k][0]);
        if (j < V && v[V - 2] != 0)
          chmax(loop_memo[V - 1][j + 1][k][1],
                loop_memo[V - 2][j][k][1] + v[V - 2]);
      } else {
        if (v[V - 1] == 0)
          continue;
        if (j < V)
          chmax(loop_memo[V - 1][j + 1][k][1],
                loop_memo[V - 2][j][k][0] + v[V - 1]);
        if (j < V && v[V - 2] != 0) {
          chmax(loop_memo[V - 1][j + 1][k][1],
                loop_memo[V - 2][j][k][1] + v[V - 2] + v[V - 1]);
        }
      }
    }
  }
  res[0] = 0;
  REP(i, res.size()) {
    REP(j, V + 1) REP(k, 2) REP(l, 2) chmax(res[i], loop_memo[j][i][k][l]);
  }
  return res;
}

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  REP(i, 2222) REP(j, 2222) dp[i][j] = -INF;
  cin >> n >> m >> k;
  Graph g(n);
  REP(i, m) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    add_edge(g, a, b, c);
    add_edge(g, b, a, c);
  }
  vector<bool> vis(n);
  vector<vi> con;
  REP(i, n) {
    if (vis[i])
      continue;
    vis[i] = true;
    vi tmp;
    tmp.push_back(i);
    queue<int> que;
    que.push(i);
    while (!que.empty()) {
      int t = que.front();
      que.pop();
      for (auto e : g[t]) {
        if (vis[e.to])
          continue;
        vis[e.to] = true;
        tmp.push_back(e.to);
        que.push(e.to);
      }
    }
    con.push_back(tmp);
  }
  sz = con.size();
  vector<bool> loop(sz);
  vi start(sz);
  REP(i, sz) {
    if (con[i].size() < 3) {
      loop[i] = false;
      start[i] = con[i][0];
      continue;
    }
    bool f = true;
    queue<int> que;
    que.push(con[i][0]);
    vector<bool> vis(n);
    vis[con[i][0]] = true;
    while (!que.empty()) {
      int t = que.front();
      que.pop();
      if (g[t].size() == 1) {
        f = false;
        start[i] = t;
        break;
      }
      for (auto e : g[t]) {
        if (vis[e.to])
          continue;
        vis[e.to] = true;
        que.push(e.to);
      }
    }
    if (f) {
      loop[i] = true;
      start[i] = con[i][0];
    }
  }
  vector<vi> weight(sz);
  REP(i, n) vis[i] = false;
  REP(i, sz) {
    vi tmp;
    if (loop[i]) {
      int t = start[i];
      vis[t] = true;
      bool f = true;
      while (f) {
        f = false;
        REP(i, g[t].size()) {
          if (vis[g[t][i].to])
            continue;
          vis[g[t][i].to] = true;
          f = true;
          tmp.push_back(g[t][i].cost);
          t = g[t][i].to;
        }
      }
      tmp.push_back(g[start[i]][1].cost);
      weight[i] = tmp;
    } else {
      int t = start[i];
      vis[t] = true;
      bool f = true;
      while (f) {
        f = false;
        REP(i, g[t].size()) {
          if (vis[g[t][i].to])
            continue;
          vis[g[t][i].to] = true;
          f = true;
          tmp.push_back(g[t][i].cost);
          t = g[t][i].to;
        }
      }
      weight[i] = tmp;
    }
  }

  value.resize(sz);
  REP(i, sz) {
    if (loop[i])
      value[i] = calc_loop(weight[i]);
    else
      value[i] = calc_line(weight[i]);
  }
  ll ans = solve(0, 0);
  if (ans < -30000000)
    cout << "Impossible" << endl;
  else
    cout << solve(0, 0) << endl;
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef int ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/

typedef int Weight;
struct Edge {
  int from, to;
  Weight cost;
  bool operator<(const Edge &e) const { return cost < e.cost; }
  bool operator>(const Edge &e) const { return cost > e.cost; }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
void add_edge(Graph &g, int from, int to, Weight cost) {
  g[from].push_back(Edge{from, to, cost});
}

int n, m, k, sz;
vector<vi> value;

ll dp[2222][2222];
ll solve(int i, int used) {
  if (i == sz) {
    if (used < k)
      return -INF + 1;
    else
      return 0;
  }
  if (dp[i][used] > -INF)
    return dp[i][used];
  ll res = -INF;
  REP(j, value[i].size()) {
    if (used + j > k)
      break;
    chmax(res, solve(i + 1, used + j) + value[i][j]);
  }
  return dp[i][used] = res;
}

vector<vector<vi>> line_memo;

vi calc_line(vi &v) {
  int V = v.size() + 1;
  if (v.size() == 0) {
    return vi{0, 0};
  }
  line_memo.clear();
  line_memo.resize(V);
  REP(i, line_memo.size()) line_memo[i].resize(V + 1);
  REP(i, line_memo.size())
  REP(j, line_memo[i].size()) line_memo[i][j].resize(2, -INF);
  vi res(V + 1, -INF);
  line_memo[0][0][0] = line_memo[0][1][1] = 0;
  REP(i, line_memo.size() - 1) REP(j, line_memo[i].size()) {
    chmax(line_memo[i + 1][j][0], max(line_memo[i][j][0], line_memo[i][j][1]));
    if (j < line_memo[i].size() - 1)
      chmax(line_memo[i + 1][j + 1][1], line_memo[i][j][0]);
    if (j < line_memo[i].size() - 1 && v[i] != 0)
      chmax(line_memo[i + 1][j + 1][1], line_memo[i][j][1] + v[i]);
  }
  res[0] = 0;
  REP(i, res.size()) {
    REP(j, line_memo.size()) REP(k, 2) chmax(res[i], line_memo[j][i][k]);
  }
  return res;
}

int loop_memo[2222][2222][2][2];

vi calc_loop(vi &v) {
  int V = v.size();
  REP(i, V + 2) REP(j, V + 2) REP(k, 2) REP(l, 2) loop_memo[i][j][k][l] = -INF;
  // loop_memo.clear();
  // loop_memo.resize(V);
  // REP(i, loop_memo.size()) loop_memo[i].resize(V + 1);
  // REP(i, loop_memo.size())REP(j, loop_memo[i].size())
  // loop_memo[i][j].resize(2); REP(i, loop_memo.size())REP(j,
  // loop_memo[i].size())REP(k, loop_memo[i][j].size())
  // loop_memo[i][j][k].resize(2, -INF);
  vi res(V + 1, -INF);
  loop_memo[0][0][0][0] = loop_memo[0][1][1][1] = 0;
  REP(i, V - 2) REP(j, V + 1) REP(k, 2) {
    chmax(loop_memo[i + 1][j][k][0],
          max(loop_memo[i][j][k][0], loop_memo[i][j][k][1]));
    if (j < V)
      chmax(loop_memo[i + 1][j + 1][k][1], loop_memo[i][j][k][0]);
    if (j < V && v[i] != 0)
      chmax(loop_memo[i + 1][j + 1][k][1], loop_memo[i][j][k][1] + v[i]);
  }

  REP(j, V + 1) {
    REP(k, 2) {
      chmax(loop_memo[V - 1][j][k][0],
            max(loop_memo[V - 2][j][k][0], loop_memo[V - 2][j][k][1]));
      if (k == 0) {
        if (j < V)
          chmax(loop_memo[V - 1][j + 1][k][1], loop_memo[V - 2][j][k][0]);
        if (j < V && v[V - 2] != 0)
          chmax(loop_memo[V - 1][j + 1][k][1],
                loop_memo[V - 2][j][k][1] + v[V - 2]);
      } else {
        if (v[V - 1] == 0)
          continue;
        if (j < V)
          chmax(loop_memo[V - 1][j + 1][k][1],
                loop_memo[V - 2][j][k][0] + v[V - 1]);
        if (j < V && v[V - 2] != 0) {
          chmax(loop_memo[V - 1][j + 1][k][1],
                loop_memo[V - 2][j][k][1] + v[V - 2] + v[V - 1]);
        }
      }
    }
  }
  res[0] = 0;
  REP(i, res.size()) {
    REP(j, V + 1) REP(k, 2) REP(l, 2) chmax(res[i], loop_memo[j][i][k][l]);
  }
  return res;
}

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  REP(i, 2222) REP(j, 2222) dp[i][j] = -INF;
  cin >> n >> m >> k;
  Graph g(n);
  REP(i, m) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    add_edge(g, a, b, c);
    add_edge(g, b, a, c);
  }
  vector<bool> vis(n);
  vector<vi> con;
  REP(i, n) {
    if (vis[i])
      continue;
    vis[i] = true;
    vi tmp;
    tmp.push_back(i);
    queue<int> que;
    que.push(i);
    while (!que.empty()) {
      int t = que.front();
      que.pop();
      for (auto e : g[t]) {
        if (vis[e.to])
          continue;
        vis[e.to] = true;
        tmp.push_back(e.to);
        que.push(e.to);
      }
    }
    con.push_back(tmp);
  }
  sz = con.size();
  vector<bool> loop(sz);
  vi start(sz);
  REP(i, sz) {
    if (con[i].size() < 3) {
      loop[i] = false;
      start[i] = con[i][0];
      continue;
    }
    bool f = true;
    queue<int> que;
    que.push(con[i][0]);
    vector<bool> vis(n);
    vis[con[i][0]] = true;
    while (!que.empty()) {
      int t = que.front();
      que.pop();
      if (g[t].size() == 1) {
        f = false;
        start[i] = t;
        break;
      }
      for (auto e : g[t]) {
        if (vis[e.to])
          continue;
        vis[e.to] = true;
        que.push(e.to);
      }
    }
    if (f) {
      loop[i] = true;
      start[i] = con[i][0];
    }
  }
  vector<vi> weight(sz);
  REP(i, n) vis[i] = false;
  REP(i, sz) {
    vi tmp;
    if (loop[i]) {
      int t = start[i];
      vis[t] = true;
      bool f = true;
      while (f) {
        f = false;
        REP(i, g[t].size()) {
          if (vis[g[t][i].to])
            continue;
          vis[g[t][i].to] = true;
          f = true;
          tmp.push_back(g[t][i].cost);
          t = g[t][i].to;
        }
      }
      tmp.push_back(g[start[i]][1].cost);
      weight[i] = tmp;
    } else {
      int t = start[i];
      vis[t] = true;
      bool f = true;
      while (f) {
        f = false;
        REP(i, g[t].size()) {
          if (vis[g[t][i].to])
            continue;
          vis[g[t][i].to] = true;
          f = true;
          tmp.push_back(g[t][i].cost);
          t = g[t][i].to;
        }
      }
      weight[i] = tmp;
    }
  }

  value.resize(sz);
  REP(i, sz) {
    if (loop[i])
      value[i] = calc_loop(weight[i]);
    else
      value[i] = calc_line(weight[i]);
  }
  ll ans = solve(0, 0);
  if (ans < -30000000)
    cout << "Impossible" << endl;
  else
    cout << solve(0, 0) << endl;
  return 0;
}