hihocoder #1122 二分图二•二分图最大匹配之匈牙利算法(*【模板】应用 )
梳理整个算法:
1. 依次枚举每一个点i;
2. 若点i尚未匹配,则以此点为起点查询一次交错路径。
最后即可得到最大匹配数。
在这个基础上仍然有两个可以优化的地方:
1.对于点的枚举:当我们枚举了所有A中的点后,无需再枚举B中的点,就已经得到了最大匹配。
2.
在查询交错路径的过程中,有可能出现Ai与Bj直接相连,其中Bj为已经匹配的点,且Bj之后找不到交错路径。之后又通过Ai查找到了一条交错路径
{Ai,Bx,Ay,…,Az,Bj}延伸到Bj。由于之前已经计算过Bj没有交错路径,若此时再计算一次就有了额外的冗余。所以我们需要枚举每个Ai时
记录B集合中的点是否已经查询过,起点不同时需要清空记录。
伪代码:
Function FindPath(u) For v∈u的相邻节点 标记v已经查询过 If v未匹配 or FindPath(v的匹配的点) Then 更改u的匹配为v Return Ture End If End For Return False For i ∈ V 清空标记 FindPath(i) End If
输入
第1行:2个正整数,N,M(N表示点数 2≤N≤1,000,M表示边数1≤M≤5,000)
第2..M+1行:每行两个整数u,v,表示一条无向边(u,v)
输出
第1行:1个整数,表示最大匹配数
- 样例输入
-
5 4 3 2 1 3 5 4 1 5
- 样例输出
-
2
代码:1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <algorithm> 6 #define N 1001 7 8 using namespace std; 9 int n, m; 10 int map[N][N]; 11 int link[N]; 12 bool vis[N]; 13 14 int dfs(int dd) 15 { 16 for(int i=1; i<=n; i++) 17 { 18 if(vis[i]==false && map[dd][i]==1 ) 19 { 20 vis[i]=true; 21 if(link[i]==-1 || dfs(link[i]) ) 22 { 23 link[i]=dd; 24 return 1; 25 } 26 } 27 } 28 return 0; 29 } 30 31 int main() 32 { 33 scanf("%d %d", &n, &m); 34 int i, j; 35 int u, v; 36 memset(map, 0, sizeof(map)); 37 memset(link, -1, sizeof(link)); 38 39 for(i=0; i<m; i++) 40 { 41 scanf("%d %d", &u, &v); 42 map[u][v]=1; 43 map[v][u]=1; 44 } 45 int cnt=0; 46 for(i=1; i<=n; i++) 47 { 48 memset(vis, false, sizeof(vis)); 49 cnt+=dfs(i); 50 } 51 printf("%d\n", cnt/2 ); 52 return 0; 53 }