Aizu Online Judge 1163 - Cards
解法
二部マッチングの問題です。
青のカードと赤のカードに書かれている数字が互いに素でなければからに辺を張ります。このように作ったグラフは二部グラフとなるのであとは最大マッチングを求めることで解を得ることができます。
ソースコード
#include <iostream> #include <vector> #include <cstring> using namespace std; #define REP(i, x) for (int i = 0; i < (x); i++) const int MAX_N = 500; const int MAX_M = 500; const int MAX_V = MAX_N + MAX_M; int V; vector<int> G[MAX_V]; int match[MAX_V]; bool used[MAX_V]; void add_edge(int u, int v) { G[u].push_back(v); G[v].push_back(u); } bool dfs(int v) { used[v] = true; for (int i = 0; i < G[v].size(); i++) { int u = G[v][i], w = match[u]; if (w < 0 || (!used[w] && dfs(w))) { match[v] = u; match[u] = v; return true; } } return false; } int bipartite_matching() { int res = 0; memset(match, -1, sizeof(match)); for (int v = 0; v < V; v++) { if (match[v] < 0) { memset(used, 0, sizeof(used)); if (dfs(v)) { res++; } } } return res; } int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } int bi[MAX_M], ri[MAX_N]; int main() { cin.tie(0); ios::sync_with_stdio(false); int m, n; while (cin >> m >> n, m | n) { V = m + n; REP (i, V) { G[i].clear(); } REP (i, m) { cin >> bi[i]; } REP (i, n) { cin >> ri[i]; } REP (i, m) { REP (j, n) { if (gcd(bi[i], ri[j]) > 1) { add_edge(i, j + m); } } } cout << bipartite_matching() << endl; } }
感想
Codeforces日記(Codeforcesしかやらないとは言っていない)
ICPCも近いので作ったばっかりですがAOJの問題が多くなると思います。