Problem p00744 (C++)

Buggy submission (status: Runtime Error):
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAXV = 2005;
const int MAXE = MAXV * MAXV;
const int INF = 1 << 29;

struct BiparateMatching {
  int N, M, E, match[MAXV + 1], dist[MAXV + 1];
  int last[MAXE], prev[MAXE], to[MAXE];
  BiparateMatching(int n, int m) : N(n), M(m), E(0) {
    memset(last, -1, sizeof(last));
  }
  void add_edge(int x, int y) { // x \in [0, N), y \in [0, M)
    to[E] = y + N;
    prev[E] = last[x];
    last[x] = E;
    E++;
  }
  bool bfs() {
    queue<int> q;
    for (int i = 0; i < N; ++i) {
      if (match[i] == -1) {
        q.push(i);
        dist[i] = 0;
      } else
        dist[i] = INF;
    }

    bool ret = false;
    while (!q.empty()) {
      int v = q.front();
      q.pop();
      for (int e = last[v]; e != -1; e = prev[e]) {
        if (match[to[e]] == -1)
          ret = true;
        else if (dist[match[to[e]]] == INF) {
          dist[match[to[e]]] = dist[v] + 1;
          q.push(match[to[e]]);
        }
      }
    }
    return ret;
  }
  bool dfs(int v) {
    for (int e = last[v]; e != -1; e = prev[e]) {
      bool update = false;
      if (match[to[e]] == -1) {
        match[to[e]] = v;
        match[v] = to[e];
        update = true;
      } else if (dist[match[to[e]]] == dist[v] + 1) {
        if (dfs(match[to[e]])) {
          match[to[e]] = v;
          match[v] = to[e];
          update = true;
        }
      }
      if (update)
        return true;
    }
    dist[v] = INF;
    return false;
  }
  int matching() {
    int ret = 0;
    memset(match, -1, sizeof(match));
    while (bfs()) {
      for (int i = 0; i < N; ++i)
        if (match[i] == -1 && dfs(i))
          ret++;
    }
    return ret;
  }
};

int gcd(int x, int y) {
  if (y == 0)
    return x;
  return gcd(y, x % y);
}

int b[501], r[501];
int main() {
  int m, n;
  while (scanf("%d %d", &m, &n), m | n) {
    BiparateMatching bm(m, n);
    for (int i = 0; i < m; ++i)
      scanf("%d", &b[i]);
    for (int i = 0; i < n; ++i)
      scanf("%d", &r[i]);
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j)
        if (gcd(b[i], r[j]) > 1)
          bm.add_edge(i, j);
    }
    printf("%d\n", bm.matching());
  }
}

Fixed submission:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAXV = 2005;
const int MAXE = 505 * 505;
const int INF = 1 << 29;

struct BiparateMatching {
  int N, M, E, match[MAXV + 1], dist[MAXV + 1];
  int last[MAXE], prev[MAXE], to[MAXE];
  BiparateMatching(int n, int m) : N(n), M(m), E(0) {
    memset(last, -1, sizeof(last));
  }
  void add_edge(int x, int y) { // x \in [0, N), y \in [0, M)
    to[E] = y + N;
    prev[E] = last[x];
    last[x] = E;
    E++;
  }
  bool bfs() {
    queue<int> q;
    for (int i = 0; i < N; ++i) {
      if (match[i] == -1) {
        q.push(i);
        dist[i] = 0;
      } else
        dist[i] = INF;
    }

    bool ret = false;
    while (!q.empty()) {
      int v = q.front();
      q.pop();
      for (int e = last[v]; e != -1; e = prev[e]) {
        if (match[to[e]] == -1)
          ret = true;
        else if (dist[match[to[e]]] == INF) {
          dist[match[to[e]]] = dist[v] + 1;
          q.push(match[to[e]]);
        }
      }
    }
    return ret;
  }
  bool dfs(int v) {
    for (int e = last[v]; e != -1; e = prev[e]) {
      bool update = false;
      if (match[to[e]] == -1) {
        match[to[e]] = v;
        match[v] = to[e];
        update = true;
      } else if (dist[match[to[e]]] == dist[v] + 1) {
        if (dfs(match[to[e]])) {
          match[to[e]] = v;
          match[v] = to[e];
          update = true;
        }
      }
      if (update)
        return true;
    }
    dist[v] = INF;
    return false;
  }
  int matching() {
    int ret = 0;
    memset(match, -1, sizeof(match));
    while (bfs()) {
      for (int i = 0; i < N; ++i)
        if (match[i] == -1 && dfs(i))
          ret++;
    }
    return ret;
  }
};

int gcd(int x, int y) {
  if (y == 0)
    return x;
  return gcd(y, x % y);
}

int b[501], r[501];
int main() {
  int m, n;
  while (scanf("%d %d", &m, &n), m | n) {
    BiparateMatching bm(m, n);
    for (int i = 0; i < m; ++i)
      scanf("%d", &b[i]);
    for (int i = 0; i < n; ++i)
      scanf("%d", &r[i]);
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j)
        if (gcd(b[i], r[j]) > 1)
          bm.add_edge(i, j);
    }
    printf("%d\n", bm.matching());
  }
}