所谓的二分图的最大匹配是指在二分图中选择出最多的边数,且选择的边不共点。
1.首先选择一个没有匹配的点x,选择x的任意一条边(x,y),如果y也没有匹配,那么就选(x,y),如果y已经被匹配了, 那么就让已经匹配y的点z去尝试找一个新的匹配;如果x和y能够匹配成功,那么匹配数就加1。
2.如果x和y没有匹配成功,那么再尝试x的另一条边;
3.对于所有的点,重复1,2两步
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=2000+10;
int pp[maxn],n,m,e,ans;
bool d[maxn][maxn],b[maxn];
int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
bool dfs(int k){
for(int i=1;i<=n;i++)
if(d[k][i]&&!b[i]){
b[i]=true;
if(!pp[i]||dfs(pp[i])){
pp[i]=k;
return true;
}
}
return false;
}
int main(){
n=read();
m=read();
e=read();
for(int i=1;i<=e;i++){
int u,v;
u=read();
v=read();
if(u>n||v>m)
continue;
d[u][v]=true;
}
for(int i=1;i<=m;i++){
memset(b,0,sizeof(b));
if(dfs(i))
ans++;
}
printf("%d",ans);
return 0;
}
二分图的多重匹配:就是点i可以用ki次【最大流】
二分图的带权匹配:边带有权值,KM,费用流
二分图的最小点(权)覆盖:
对于一张二分图G(V,E),从V中选择一个子集S,使得图中所有的边至少有1个端点落在S中,这样的最小的点数的S就称之为G的最小点覆盖。
最小点覆盖==最大匹配
二分图的最大独立集:
对于一张无向图G(V,E ),选出一个V的子集S,使得S中任意两点之间都没有边,且S是最大的这样的子集。
如何求二分图的最大独立集:
最大独立集点的数量==N-二分图的最大匹配
证明:要使得独立集越大,那么删掉的点就要越少,同时还要保证删掉的点覆盖到所有的边,所以删掉的应该是最小点覆盖
最小路径点覆盖:对于一张有向无环图(DAG),用尽量少的简单路径(没有重复经过点的)覆盖所有的点。每一个点只能恰好被覆盖一次。这样的问题就是有向无环图的最小路径点覆盖。
如何求:首先,将原图中的每一个点
x拆成x和(x+n),这样就可以分成1-n和n+1到2n两个点集
然后,在原图中x->y的这条边,转化成x->(y+n),得到一张新图G’
原图的最小路径点覆盖==N-G’的最大匹配