AOJ 1163 Cards

Ford-Fulkerson法を最近勉強したのでやっと解けるようになった。

二部グラフの最大マッチングのサイズを求めるという典型題中の典型題。

#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);i++)

//Ford-Fulkerson's algorithm
struct edge{int to,cap,rev;};
const int INF=1e9;

void addEdge(vector<vector<edge> > &g,int from,int to,int cap){
    g[from].push_back((edge){to,cap,(int)g[to].size()});
    g[to].push_back((edge){from,0,(int)g[from].size()-1});
}

int dfs(vector<vector<edge> > &g,vector<bool> &used,int v,int t,int f){
    if(v==t) return f;
    used[v]=true;
    for(int i=0;i<(int)g[v].size();i++){
        edge& e=g[v][i];
        if(!used[e.to] && e.cap>0){
            int d=dfs(g,used,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 FordFulkerson(vector<vector<edge> > &g,int s,int t){
    int flow=0;
    for(;;){
        vector<bool> used(g.size(),false);
        int f=dfs(g,used,s,t,INF);
        if(f==0) return flow;
        flow+=f;
    }
}
//

int gcd(int a,int b){
    if(a<b) swap(a,b);
    if(b==0) return a;
    return gcd(b,a%b);
}

int main(){
	int m,n;
    while(cin >> m >> n && m){
        vector<int> b(m),r(n);
        REP(i,m) cin >> b[i];
        REP(i,n) cin >> r[i];
        vector<vector<edge> > g(m+n+2);
        REP(i,m) addEdge(g,0,i+1,1);
        REP(i,n) addEdge(g,m+1+i,m+n+1,1);
        REP(i,m)REP(j,n){
            if(gcd(b[i],r[j])>1) addEdge(g,i+1,m+1+j,1);
        }
        cout << FordFulkerson(g,0,m+n+1) << endl;
    }
	return 0;
}