解くのは初めてではないんだけど、何となくフローを描いてみたくなったのでやってみた。
#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#define REP(i, n) for(int i=0; i<(int)n; ++i)
#define FOR(i, c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(),(c).end()
#define each(i, c) FOR(i, c)
#define VAR(a) cout << #a << " : " << a << endl;
typedef long long int lli;
using namespace std;
struct E {
int src, dst;
E(int s, int d) : src(s), dst(d) {}
};
const int RED = 500 + 1;
const int BLUE = 500 + 1;
const int V = RED + BLUE + 2;
vector<E> g[V];
bool vis[V];
int c[V][V];
int path[V];
bool rec(int node, int snk)
{
vis[node] = true;
if (node == snk) return true;
for (int i = 0; i < (int)g[node].size(); ++i) {
E e = g[node][i];
if (vis[e.dst] || c[e.src][e.dst] <= 0) continue;
path[e.dst] = e.src;
if (rec(e.dst, snk)) return true;
}
return false;
}
int flow(int src, int snk)
{
fill(path, path + V, 0);
int sum = 0;
while (rec(src, snk)) {
fill(vis, vis + V, false);
for (int i = snk; path[i]; i = path[i]) {
--c[path[i]][i];
++c[i][path[i]];
}
++sum;
}
return sum;
}
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main(int argc, char *argv[])
{
int red, blue;
while (cin >> red >> blue && (red | blue)) {
fill(g, g + V, vector<E>());
fill(&c[0][0], &c[V - 1][V], 0);
fill(vis, vis + V, false);
int r[red];
for (int i = 0; i < (int)red; ++i) {
cin >> r[i];
}
int b[blue];
for (int i = 0; i < (int)blue; ++i) {
cin >> b[i];
}
const int R = 0, B = 1;
map<int, int> name[2];
int cnt = 1;
for (int i = 0; i < (int)red; ++i) {
name[R][i] = cnt++;
}
for (int i = 0; i < (int)blue; ++i) {
name[B][i] = cnt++;
}
const int src = cnt++;
const int snk = cnt++;
for (int i = 0; i < (int)red; ++i) {
for (int j = 0; j < (int)blue; ++j) {
int n = gcd(max(r[i], b[j]), min(r[i], b[j]));
if (n != 1) {
int a = name[R][i];
int b = name[B][j];
g[a].push_back(E(a, b));
g[b].push_back(E(b, a));
c[a][b] = 1;
}
}
}
for (int i = 0; i < (int)red; ++i) {
int n = name[R][i];
g[src].push_back(E(src, n));
c[src][n] = 1;
}
for (int i = 0; i < (int)blue; ++i) {
int n = name[B][i];
g[n].push_back(E(n, snk));
c[n][snk] = 1;
}
cout << flow(src, snk) << endl;
}
return 0;
}