Language: C++

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;

#define pb push_back
#define mp make_pair
#define ff first
#define ss second

typedef long long ll;
typedef vector<ll> vi;
typedef vector<vi> vvi;

const int MAX_P = 10000;
const int MAX_V = 1010;
const int INF = 0x3f3f3f3f;

int M, N;
vector<bool> isPrime(MAX_P, true);
vi primes;

// 辺を表す構造体（行き先、容量、逆辺）
struct edge { int to, cap, rev; };

class MF {
public:
  vector<edge> G[MAX_V];  // グラフの隣接リスト表現
  bool used[MAX_V];   // DFSですでに調べたかのフラグ

  // fromからtoへ向かう容量capの辺をグラフに追加する
  void add_edge(int from, int to, int cap) {
    G[from].push_back((edge){to, cap, G[to].size()});
    G[to].push_back((edge){from, 0, G[from].size() - 1});
  }

  // 増加パスをDFSで探す
  int dfs(int v, int t, int f) {
    if(v == t) return f;
    used[v] = true;
    for(int i = 0; i < G[v].size(); i++) {
      edge &e = G[v][i];
      if(!used[e.to] && e.cap > 0) {
        int d = dfs(e.to, t, min(f, e.cap));
        if(d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }

  int max_flow(int s, int t) {
    int flow = 0;
    for(;;) {
      memset(used, 0, sizeof(used));
      int f = dfs(s, t, INF);
      if(f == 0) return flow;
      flow += f;
    }
  }
};

void init() {
  isPrime[0] = isPrime[1] = false;
  for (int i = 0; i < MAX_P; i++) {
    if (!isPrime[i]) continue;
    primes.pb(i);
    for (int j = i; j < MAX_P; j+=i) {
      isPrime[j] = false;
    }
  }
}

int main() {
  init();
  while (true) {
    vi Bs, Rs;
    cin >> M >> N;
    if (M==0 && N==0) {
      break;
    }
    MF mf;
    for (int i = 0; i < M; i++) {
      int b; cin >> b;
      Bs.pb(b);
      mf.add_edge(0, i+1, 1);
    }
    for (int i = 0; i < N; i++) {
      int r; cin >> r;
      Rs.pb(r);
      mf.add_edge(i+M+1, M+N+1, 1);
    }
    for (int i = 0; i < M; i++) {
      for (int j = 0; j < N; j++) {
        for (int k = 0; k < (int)primes.size(); k++) {
          if (Bs[i]%primes[k]==0 && Rs[j]%primes[k]==0) {
            // cout << i+1 << ", " << j+1 << endl;
            mf.add_edge(i+1, j+M+1, 1);
            break;
          }
        }
      }
    }
    cout << mf.max_flow(0, M+N+1) << endl;
  }

  return 0;
}



Compiler output:
a.cc: In member function 'void MF::add_edge(int, int, int)':
a.cc:38:49: warning: narrowing conversion of '((MF*)this)->MF::G[to].std::vector<edge>::size()' from 'std::vector<edge>::size_type' {aka 'long unsigned int'} to 'int' [-Wnarrowing]
   38 |     G[from].push_back((edge){to, cap, G[to].size()});
      |                                       ~~~~~~~~~~^~
a.cc:39:52: warning: narrowing conversion of '(((MF*)this)->MF::G[from].std::vector<edge>::size() - 1)' from 'std::vector<edge>::size_type' {aka 'long unsigned int'} to 'int' [-Wnarrowing]
   39 |     G[to].push_back((edge){from, 0, G[from].size() - 1});
      |                                     ~~~~~~~~~~~~~~~^~~
a.cc: In member function 'int MF::max_flow(int, int)':
a.cc:63:7: error: 'memset' was not declared in this scope
   63 |       memset(used, 0, sizeof(used));
      |       ^~~~~~
a.cc:8:1: note: 'memset' is defined in header '<cstring>'; this is probably fixable by adding '#include <cstring>'
    7 | #include <algorithm>
  +++ |+#include <cstring>
    8 |