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

 


posted @ 2015-03-03 13:34  我喜欢旅行  阅读(243)  评论(0编辑  收藏  举报