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

#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <vector>

using namespace std;

typedef long long ll;

class pass {
public:
  ll t;
  ll c;
  ll p;
};

class scale {
private:
  ll v, e;

  pass *p;

  vector<ll> *node;
  bool *used;
  ll *nowin;

public:
  void set(ll vw, ll ew) {
    v = vw;
    p = new pass[ew * 2];
    node = new vector<ll>[v];
    used = new bool[v];
    nowin = new ll[v];
    e = 0;
  }

  void add(ll f, ll t, ll c) {
    p[e].t = t;
    p[e].c = c;
    p[e].p = e + 1;
    p[e + 1].t = f;
    p[e + 1].c = 0;
    p[e + 1].p = e;
    node[f].push_back(e);
    node[t].push_back(e + 1);
    e += 2;
  }

  ll solve() {
    ll nn = 0;
    for (auto i : node[0]) {
      nn = max(nn, p[i].c);
    }
    while (nn > 0) {
      stack<ll> st;
      queue<ll> q;
      for (ll i = 0; i < v; i++) {
        used[i] = false;
        nowin[i] = 0;
      }
      q.push(0);
      used[0] = true;
      while (!q.empty()) {
        ll np = q.front();
        q.pop();
        st.push(np);
        for (auto i : node[np]) {
          if (p[i].c > 0) {
            ll t = p[i].t;
            nowin[t] += p[i].c;
            if (nowin[t] >= nn && !used[t]) {
              if (t == v - 1) {
                st.push(t);
                goto aa;
              }
              q.push(t);
              used[t] = true;
            }
          }
        }
      }
    aa:
      if (st.top() != v - 1) {
        nn /= 2;
        continue;
      }
      while (!q.empty()) {
        used[q.front()] = false;
        q.pop();
      }
      for (int i = 0; i < v; i++) {
        nowin[i] = 0;
      }
      nowin[v - 1] = nn;
      while (st.size() > 1) {
        ll np = st.top();
        st.pop();
        for (auto i : node[np]) {
          ll h = p[i].p;
          if (used[p[i].t] && p[h].c > 0) {
            ll w = min(p[h].c, nowin[np]);
            p[h].c -= w;
            p[i].c += w;
            nowin[np] -= w;
            nowin[p[i].t] += w;
            if (nowin[np] == 0) {
              break;
            }
          }
        }
        used[np] = false;
      }
    }
    ll all = 0;
    for (auto i : node[0]) {
      if (i % 2 == 0) {
        all += p[p[i].p].c;
      }
    }
    return all;
  }

  void del() {
    delete[] p;
    delete[] node;
    delete[] used;
    delete[] nowin;
  }
};

ll dn[2000];
ll dm[2000];

ll gcd(ll a, ll b) {
  if (a % b == 0) {
    return b;
  }
  return gcd(b, a % b);
}

int main() {
  while (1) {
    scale a;
    ll n, m;
    scanf("%lld%lld", &n, &m);
    if (n == 0) {
      break;
    }
    a.set(n + m + 2, n * m * 2);
    for (ll i = 0; i < n; i++) {
      scanf("%lld", &dn[i]);
      a.add(0, 1 + i, 1);
    }
    for (ll i = 0; i < m; i++) {
      scanf("%lld", &dm[i]);
      a.add(n + 1 + i, n + m + 1, 1);
    }
    for (ll i = 0; i < n; i++) {
      for (ll ii = 0; ii < m; ii++) {
        if (1 < gcd(dn[i], dm[ii])) {
          a.add(1 + i, n + 1 + ii, 1);
        }
      }
    }
    printf("%lld\\n", a.solve());
    a.del();
  }
  return 0;
}

Error: MLE

Fixed submission:

#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <vector>

using namespace std;

typedef long long ll;

class pass {
public:
  ll t;
  ll c;
  ll p;
};

class scale {
private:
  ll v, e;

  pass *p;

  vector<ll> *node;
  bool *used;
  ll *nowin;

public:
  void set(ll vw, ll ew) {
    v = vw;
    p = new pass[ew * 2];
    node = new vector<ll>[v];
    used = new bool[v];
    nowin = new ll[v];
    e = 0;
  }

  void add(ll f, ll t, ll c) {
    p[e].t = t;
    p[e].c = c;
    p[e].p = e + 1;
    p[e + 1].t = f;
    p[e + 1].c = 0;
    p[e + 1].p = e;
    node[f].push_back(e);
    node[t].push_back(e + 1);
    e += 2;
  }

  ll solve() {
    ll nn = 0;
    for (auto i : node[0]) {
      nn = max(nn, p[i].c);
    }
    while (nn > 0) {
      stack<ll> st;
      queue<ll> q;
      for (ll i = 0; i < v; i++) {
        used[i] = false;
        nowin[i] = 0;
      }
      q.push(0);
      used[0] = true;
      while (!q.empty()) {
        ll np = q.front();
        q.pop();
        st.push(np);
        for (auto i : node[np]) {
          if (p[i].c > 0) {
            ll t = p[i].t;
            nowin[t] += p[i].c;
            if (nowin[t] >= nn && !used[t]) {
              if (t == v - 1) {
                st.push(t);
                goto aa;
              }
              q.push(t);
              used[t] = true;
            }
          }
        }
      }
    aa:
      if (st.top() != v - 1) {
        nn /= 2;
        continue;
      }
      while (!q.empty()) {
        used[q.front()] = false;
        q.pop();
      }
      for (int i = 0; i < v; i++) {
        nowin[i] = 0;
      }
      nowin[v - 1] = nn;
      while (st.size() > 1) {
        ll np = st.top();
        st.pop();
        for (auto i : node[np]) {
          ll h = p[i].p;
          if (used[p[i].t] && p[h].c > 0) {
            ll w = min(p[h].c, nowin[np]);
            p[h].c -= w;
            p[i].c += w;
            nowin[np] -= w;
            nowin[p[i].t] += w;
            if (nowin[np] == 0) {
              break;
            }
          }
        }
        used[np] = false;
      }
    }
    ll all = 0;
    for (auto i : node[0]) {
      if (i % 2 == 0) {
        all += p[p[i].p].c;
      }
    }
    return all;
  }

  void del() {
    delete[] p;
    delete[] node;
    delete[] used;
    delete[] nowin;
  }
};

ll dn[2000];
ll dm[2000];

ll gcd(ll a, ll b) {
  if (a % b == 0) {
    return b;
  }
  return gcd(b, a % b);
}

int main() {
  while (1) {
    scale a;
    ll n, m;
    scanf("%lld%lld", &n, &m);
    if (n == 0) {
      break;
    }
    a.set(n + m + 2, n * m * 2);
    for (ll i = 0; i < n; i++) {
      scanf("%lld", &dn[i]);
      a.add(0, 1 + i, 1);
    }
    for (ll i = 0; i < m; i++) {
      scanf("%lld", &dm[i]);
      a.add(n + 1 + i, n + m + 1, 1);
    }
    for (ll i = 0; i < n; i++) {
      for (ll ii = 0; ii < m; ii++) {
        if (1 < gcd(dn[i], dm[ii])) {
          a.add(1 + i, n + 1 + ii, 1);
        }
      }
    }
    printf("%lld\\n", a.solve());
  }
  return 0;
}