二分圖:我的理解是,對圖中的點集,可分爲兩個集合U和V,使得兩個集合之間存在通路,且集合內部不存在通路。如上圖。
匹配:兩兩不含公共端點的邊集合M
最大匹配:邊數最多的匹配
完美匹配:最大匹配的匹配數滿足2*M=點的總數
二分圖匹配:二分圖中的匹配
實際上,可將二分圖最大匹配問題看作是最大流問題的特殊情況。
最大流方法解決二分圖匹配:
將原圖中的所有無向邊e改爲有向邊,方向從U到V,容量爲1.增加原點s和匯點t,從s向所有的頂點u∈U連一條容量爲1的邊,從所有的頂點v∈V連一條容量爲1的邊。
ff方法解決二分圖匹配(洛谷p3386):
class Main{
static int maxn=1010;
static ArrayList<edge> G[]=new ArrayList[2*maxn];
static boolean vis[]=new boolean[2*maxn];
static class edge{
int to,cap,rev;
public edge(int to,int cap,int rev) {
this.to=to;
this.cap=cap;
this.rev=rev;
}
}
static boolean dfs(int v,int t){
if(v==t){
return true;
}
vis[v]=true;
int u,cap,rev;
for(int i=0;i<G[v].size();i++){
u=G[v].get(i).to;
cap=G[v].get(i).cap;
rev=G[v].get(i).rev;
if(!vis[u]&&cap>0&&dfs(u,t)){
G[u].get(rev).cap++;
G[v].get(i).cap--;
return true;
}
}
return false;
}
static void add_edge(int v,int u){
G[v].add(new edge(u,1,G[u].size()));
G[u].add(new edge(v,0,G[v].size()-1));
}
static int max_flow(int s,int t){
int res=0;
for(;;){
for(int i=0;i<2*maxn;i++) {
vis[i]=false;
}
if(dfs(s,t)) {
res++;
}else {
break;
}
}
return res;
}
public static void main(String args[]){
InputReader sc=new InputReader(System.in);
PrintWriter out =new PrintWriter(System.out);
int n=sc.nextInt();
int m=sc.nextInt();
int e=sc.nextInt();
for(int i=1;i<=n+m+10;i++) {
G[i]=new ArrayList<>();
}
int u,v;
for(int i=0;i<e;i++) {
u=sc.nextInt();
v=sc.nextInt();
if(v<=m&&u<=n) {
add_edge(u, v+n);
}
}
int s=n+m+1;
int t=s+1;
G[s]=new ArrayList<edge>();
G[t]=new ArrayList<edge>();
for(int i=1;i<=n;i++) {
add_edge(s, i);
}
for(int i=n+1;i<=n+m;i++) {
add_edge(i, t);
}
out.println(max_flow(s,t));
out.flush();
out.close();
}
}