Problem p00744 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using namespace std;

struct Bipartite_Matching {
  vector<vector<int>> graph;
  vector<int> dist, match;
  vector<bool> used, vv;

  Bipartite_Matching(int n, int m) {
    graph.resize(n);
    match.assign(m, -1);
    used.assign(n, false);
  }

  void add_edge(int u, int v) { graph[u].push_back(v); }

  void bfs() {
    dist.assign(graph.size(), -1);
    queue<int> que;
    for (int i = 0; i < graph.size(); i++) {
      if (!used[i]) {
        que.emplace(i);
        dist[i] = 0;
      }
    }

    while (!que.empty()) {
      int a = que.front();
      que.pop();
      for (auto &b : graph[a]) {
        int c = match[b];
        if (c >= 0 && dist[c] == -1) {
          dist[c] = dist[a] + 1;
          que.emplace(c);
        }
      }
    }
  }

  bool dfs(int a) {
    vv[a] = true;
    for (auto &b : graph[a]) {
      int c = match[b];
      if (c < 0 || (!vv[c] && dist[c] == dist[a] + 1 && dfs(c))) {
        match[b] = a;
        used[a] = true;
        return (true);
      }
    }
    return (false);
  }

  int bipartite_matching() {
    int ret = 0;
    while (true) {
      bfs();
      vv.assign(graph.size(), false);
      int flow = 0;
      for (int i = 0; i < graph.size(); i++) {
        if (!used[i] && dfs(i))
          ++flow;
      }
      if (flow == 0)
        return (ret);
      ret += flow;
    }
  }
};

int dp[1000][1000];

int gcd(int x, int y) {
  if (x < 1000) {
    if (~dp[x][y])
      return (dp[x][y]);
    int r = x % y;
    if (r == 0)
      return dp[x][y] = y;
    return dp[x][y] = gcd(y, r);
  } else {
    int r = x % y;
    if (r == 0)
      return y;
    return gcd(y, r);
  }
}

int main() {
  memset(dp, -1, sizeof(dp));

  int M, N, B[500], R[500];
  while (scanf("%d %d", &M, &N), M) {
    Bipartite_Matching flow(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(min(B[i], R[j]), max(B[i], R[j])) > 1)
          flow.add_edge(i, j);
      }
    }
    printf("%d\n", flow.bipartite_matching());
  }
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

struct Bipartite_Matching {
  vector<vector<int>> graph;
  vector<int> dist, match;
  vector<bool> used, vv;

  Bipartite_Matching(int n, int m) {
    graph.resize(n);
    match.assign(m, -1);
    used.assign(n, false);
  }

  void add_edge(int u, int v) { graph[u].push_back(v); }

  void bfs() {
    dist.assign(graph.size(), -1);
    queue<int> que;
    for (int i = 0; i < graph.size(); i++) {
      if (!used[i]) {
        que.emplace(i);
        dist[i] = 0;
      }
    }

    while (!que.empty()) {
      int a = que.front();
      que.pop();
      for (auto &b : graph[a]) {
        int c = match[b];
        if (c >= 0 && dist[c] == -1) {
          dist[c] = dist[a] + 1;
          que.emplace(c);
        }
      }
    }
  }

  bool dfs(int a) {
    vv[a] = true;
    for (auto &b : graph[a]) {
      int c = match[b];
      if (c < 0 || (!vv[c] && dist[c] == dist[a] + 1 && dfs(c))) {
        match[b] = a;
        used[a] = true;
        return (true);
      }
    }
    return (false);
  }

  int bipartite_matching() {
    int ret = 0;
    while (true) {
      bfs();
      vv.assign(graph.size(), false);
      int flow = 0;
      for (int i = 0; i < graph.size(); i++) {
        if (!used[i] && dfs(i))
          ++flow;
      }
      if (flow == 0)
        return (ret);
      ret += flow;
    }
  }
};

int dp[1000][1000];

int gcd(int x, int y) {
  if (x < 1000) {
    if (~dp[x][y])
      return (dp[x][y]);
    int r = x % y;
    if (r == 0)
      return dp[x][y] = y;
    return dp[x][y] = gcd(y, r);
  } else {
    int r = x % y;
    if (r == 0)
      return y;
    return gcd(y, r);
  }
}

int main() {
  memset(dp, -1, sizeof(dp));

  int M, N, B[500], R[500];
  while (scanf("%d %d", &M, &N), M) {
    Bipartite_Matching flow(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(max(B[i], R[j]), min(B[i], R[j])) > 1)
          flow.add_edge(i, j);
      }
    }
    printf("%d\n", flow.bipartite_matching());
  }
}