二分匹配 匈牙利算法

算法讲解:http://imlazy.ycool.com/post.1603708.html

dfs实现

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 using namespace std;
5 int g[505][505],m[505],n[505],vist[505];
6 int k,mm,gg,sum;
7 int search1(int i)
8 {
9 int j;
10 for (j=1;j<=gg;j++)
11 {
12 if (g[i][j]==1&&!vist[j])
13 {
14 vist[j]=1;
15 if (n[j]==-1||search1(n[j]))
16 {
17 m[i]=j;
18 n[j]=i;
19 return 1;
20 }
21 }
22 }
23 return 0;
24 }
25 void maxmatch()
26 {
27 int i;
28 memset(m,-1,sizeof(m));
29 memset(n,-1,sizeof(n));
30 for (i=1;i<=mm;i++)
31 {
32 if(m[i]==-1)
33 {
34 memset(vist,0,sizeof(vist));
35 if(search1(i))
36 sum++;
37 }
38 }
39 }
40 int main()
41 {
42 int i,t,x,y;
43 scanf("%d",&k);
44 while (k--)
45 {
46 sum=0;
47 scanf("%d%d",&mm,&t);
48 gg=mm;
49 memset(g,0,sizeof(g));
50 for (i=1;i<=t;i++)
51 {
52 scanf("%d%d",&x,&y);
53 g[x][y]=1;
54 }
55 maxmatch();
56 printf("%d\n",sum);
57 }
58 return 0;
59 }

 BFS实现

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 using namespace std;
5 //匈牙利算法实现
6 #define MAX 510 //二部图一侧顶点的最大个数
7 int n,m; //二分图的两个集合分别含有n和m个元素。
8
9 bool map[MAX][MAX]; //map存储邻接矩阵。
10
11 int Bipartite()
12 {
13 int i, j, x, ans; //ans为最大匹配数
14
15 int q[MAX], prev[MAX], qs, qe;
16 //q是BFS用的队列,prev是用来记录交错链的,同时也用来记录右边的点是否被找过
17
18 int vm1[MAX], vm2[MAX];
19 //vm1,vm2分别表示两边的点与另一边的哪个点相匹配
20
21 ans = 0;
22 memset(vm1, -1, sizeof(vm1));
23 memset(vm2, -1, sizeof(vm2)); //初始化所有点为未被匹配的状态
24
25 for( i = 1; i<=n; i++ )
26 {
27 if(vm1[i] != -1)continue; //对于左边每一个未被匹配的点进行一次BFS找交错链
28
29 for( j = 1; j<=m; j++ ) prev[j] = -2; //每次BFS时初始化右边的点
30
31 qs = qe = 0; //初始化BFS的队列
32
33 //下面这部分代码从初始的那个点开始,先把它能找的的右边的点放入队列
34 for( j = 1; j <= m; j++ )
35 {
36 if( map[i][j] )
37 {
38 prev[j] = -1;
39 q[qe++] = j;
40 }
41 }
42
43 while( qs < qe )
44 { //BFS
45 x = q[qs];
46 if( vm2[x] == -1 ) break;
47 //如果找到一个未被匹配的点,则结束,找到了一条交错链
48 qs++;
49 //下面这部分是扩展结点的代码
50 for( j = 1; j<=m; j++ )
51 {
52 if( prev[j] == -2 && map[vm2[x]][j] )
53 {
54 //如果该右边点是一个已经被匹配的点,则vm2[x]是与该点相匹配的左边点
55 //从该左边点出发,寻找其他可以找到的右边点
56 prev[j] = x;
57 q[qe++] = j;
58 }
59 }
60 }
61 if( qs == qe ) continue; //没有找到交错链
62
63 //更改交错链上匹配状态
64 while( prev[x] > -1 )
65 {
66 vm1[vm2[prev[x]]] = x;
67 vm2[x] = vm2[prev[x]];
68 x = prev[x];
69 }
70 vm2[x] = i;
71 vm1[i] = x;
72
73 //匹配的边数加一
74 ans++;
75 }
76 return ans;
77 }
78 int main()
79 {
80 int i,x,t,y,k,sum;
81 scanf("%d",&k);
82 while (k--)
83 {
84
85 sum=0;
86 scanf("%d%d",&n,&t);
87 m=n;
88 memset(map,0,sizeof(map));
89 for (i=1;i<=t;i++)
90 {
91 scanf("%d%d",&x,&y);
92 map[x][y]=1;
93 }
94 sum=Bipartite();
95 printf("%d\n",sum);
96 }
97 return 0;
98 }

  

posted @ 2011-08-09 11:22  我们一直在努力  阅读(286)  评论(0)    收藏  举报