二分图匹配

二分图匹配

之前写过二分图匹配的博客,但就是感觉看了那篇博客也无法真正懂得二分图匹配,所以就再写一篇了。

先普及一下概念:

二分图:可以被分为两个子集且保证每个子集中的元素不直接相连的图。

交替路:从一个未匹配点出发,依次经过未匹配边,匹配边,未匹配边......形成的路径叫做交替路。

增广路:从一个未匹配点出发,经过交替路,如果途径一个未匹配点,就把走过的路径叫做增广路。

最大匹配:在一个图的所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。

完美匹配:一个图的所有顶点都是匹配点,那么这个图就是最大匹配。

从增广路的定义上我们可以发现,每一条增广路所包含的未匹配点总比匹配点多一个。如果把增广路的所有匹配点变为未匹配点,未匹配点变为匹配点,每进行这样一次操作,未匹配点都会变少一个。我们可以每次在这个图上寻找增广路,然后进行这样的操作,直到在这个图上找不到增广路为止。而进行完这些操作后,所形成的图就是一个最大匹配的图。

下面用DFS来实现:

 1 #include<cstdio>
 2 #include<cstring>
 3 #define N 42000
 4 int next[N],to[N],num,head[N],vis[N],used[N],n,m,a,b,ans;
 5 void add(int false_from,int false_to){
 6     next[++num]=head[false_from];
 7     to[num]=false_to;
 8     head[false_from]=num;
 9 }
10 int dfs(int x){
11     for(int i=head[x];i;i=next[i])
12         if(!vis[to[i]]){
13             vis[to[i]]=1;
14             if(!used[to[i]]||dfs(used[to[i]])){
15                 used[to[i]]=x;
16                 return 1;
17             }
18         }
19     return 0;
20 }
21 int main(){
22     scanf("%d%d",&n,&m);
23     for(int i=1;i<=m;++i){
24         scanf("%d%d",&a,&b);
25         add(a,b);
26         add(b,a);
27     }
28     for(int i=1;i<=n;++i)
29         if(!vis[i]){
30             memset(used,0,sizeof(used));
31             if(dfs(i))
32                 ans++;
33         }
34     printf("%d",ans);
35     return 0;
36 }
View Code
原文地址:https://www.cnblogs.com/jsawz/p/6855307.html