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 }
View Code

 

 
   

你可能感兴趣的:(code)