对二分图一边的每一个点 dfs ,寻找它的所有匹配点,若那个匹配点没有匹配过或匹配的另一半能新找一个点与之匹配,那么就重组后分别匹配,否则不能匹配

 

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 const int maxn=1e5+5;
 5 const int maxm=1e5+5;
 6 
 7 int head[maxn],point[maxm],nxt[maxm],size;
 8 int match[maxn],vis[maxn];
 9 
10 void init(){
11     memset(head,-1,sizeof(head));
12     size=0;
13     memset(match,-1,sizeof(match));
14 }
15 
16 void add(int a,int b){
17     point[size]=b;
18     nxt[size]=head[a];
19     head[a]=size++;
20 }
21 
22 int dfs(int s){
23     for(int i=head[s];~i;i=nxt[i]){
24         int j=point[i];
25         if(!vis[j]){
26             vis[j]=1;
27             if(match[j]==-1||dfs(match[j])){
28                 match[j]=s;
29                 return 1;
30             }
31         }
32     }
33     return 0;
34 }
35 
36 for(int i=1;i<=n;++i){
37     memset(vis,0,sizeof(vis));
38     if(dfs(i)==1)ans++;
39 }

 

 

 

 

然后,关于二分图还有几个个专门的问题:最小路径覆盖和最小点覆盖、二分图的最大独立集

 

最小路径覆盖,就是在一个有向无环图中,用最少的路径将所有点覆盖,保证每个点存在且仅存在于一条路径上。

其做法是将原图中的每个点拆成一个入点和一个出点,对于原图中的每条有向边,在新图中建立出发点的出点到进入点的入点的边,然后对于新图进行二分图最大匹配,而:

最小路径覆盖数 = 原图的点数 - 最大匹配数

最小点覆盖数 = 最大匹配数

二分图的最大独立集数 = 原图的点数 - 最大匹配数

 

 

还有一个问题是二分图关键匹配,即达到最大匹配的必须匹配,可以通过求一遍最大匹配记录下每个点的匹配,然后删去每个匹配时,若不能找到增广路则删去的是关键匹配。

 

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 const int maxn=1e5+5;
 5 const int maxm=1e5+5;
 6 
 7 int head[maxn],point[maxm],nxt[maxm],size;
 8 int match[maxn],vis[maxn];
 9 int get[maxn];
10 
11 void init(){
12     memset(head,-1,sizeof(head));
13     size=0;
14     memset(match,-1,sizeof(match));
15     memset(get,-1,sizeof(get));
16 }
17 
18 void add(int a,int b){
19     point[size]=b;
20     nxt[size]=head[a];
21     head[a]=size++;
22 }
23 
24 int del;
25 
26 int dfs(int s,bool F){
27     for(int i=head[s];~i;i=nxt[i]){
28         if(!F&&i==del)continue;
29         int j=point[i];
30         if(!vis[j]){
31             vis[j]=1;
32             if(match[j]==-1||dfs(match[j],F)){
33                 if(F){
34                     match[j]=s;
35                     get[s]=i;
36                 }
37                 return 1;
38             }
39         }
40     }
41     return 0;
42 }
43 
44 
45         int ans1=0;
46         for(int i=1;i<=n;++i){
47             memset(vis,0,sizeof(vis));
48             if(dfs(i,1))ans1++;
49         }
50         int ans=0;
51         for(int i=1;i<=n;++i){
52             if(get[i]!=-1){
53                 del=get[i];
54                 match[point[del]]=-1;
55                 get[i]=-1;
56                 memset(vis,0,sizeof(vis));
57                 if(!dfs(i,0))ans++;
58                 get[i]=del;
59                 match[point[del]]=i;
60             }
61         }