二分图最大匹配
二分图匹配:每个左部点最多与一个右部点相连,每个右部点最多与一个左部点相连
算法流程:
如果后来的和以前的发生矛盾,则以前的优先退让。
如果以前的退让之后没有点与之相连,则以前的拒绝退让,新来的去寻找下一个匹配。
如果新来的谁也匹配不上,就匹配不上吧:
学会了二分图最大匹配后,另外几种模型也可求解。
最小点覆盖
最小点覆盖:选取最少的点,使得所有的点与至少一个被选取点距离不超过1,或选取最少的点,使得所有边都至少与一个被选取点相连
方法:最小点覆盖=最大匹配
最大独立集
最大独立集:选取最多的点,使得其中任意两点互不相达
方法:最大独立集 = 点总数 - 最大匹配
最小边覆盖
最小边覆盖:选取最少的边使得所有的点被至少一条边覆盖
方法:最小边覆盖 = 总点数 - 最大匹配
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=5e4+10;
int read(){
int x=1,a=0;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') x=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
return x*a;
}
struct node{
int to,next;
}ed[maxn];
int head[maxn],tot;
int matc[maxn],vis[maxn];
void add(int u,int to){
ed[++tot].to=to;
ed[tot].next=head[u];
head[u]=tot;
}
int n,m,e;
bool dfs(int x){
for(int i = head[x];i;i=ed[i].next){
int to=ed[i].to;
if (vis[to]) continue; vis[to]=1;
if (matc[to]==0||dfs(matc[to])){
matc[to]=x;
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();
add(u,v);
}
int ans=0;
for(int i = 1;i <= n;i++){
memset(vis,0,sizeof(vis));
if (dfs(i)) ans++;
}
printf("%d
",ans);
return 0;
}