二分图:我的理解是,对图中的点集,可分为两个集合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();
}
}