解题报告:有m个女生和n个男生要结成伴坐过山车,每个女生都有几个自己想选择的男生,然后要你确定最多能组成多少对组合。
最裸的一个二分匹配,这是我第一次写二分匹配,给我最大的感受就是看那些人讲的匈牙利算法真不知道他们是怎么写的,看着就觉得很麻烦,好像很难的样子,我这是看第二次,最后还是没看懂,最后实在没办法了,直接看代码了,才发现,原来二分匹配可以用很简单的描述,下面我就用我的语言描述一下:
假如分成两个集合X和Y,我们可以从X 中的第一个元素枚举到最后一个,然后每次枚举的内容就是从X 出发,找这个元素能不能跟Y中的一个元素进行匹配,关键就是这个查找的函数,这个可以用dfs或者bfs,这里我就讲用dfs实现的,枚举X中的一个元素的时候,我们就从这个元素出发,从Y的元素开始枚举,如果Y的有元素还没有被匹配,则返回,就将这两个元素匹配起来,而如果这个Y中的元素在前面已经被匹配过了,那么就递归,看跟Y匹配的是X中的哪一个元素,其实说白了就是看X中的这个元素还能不能跟Y中的其它元素匹配,就是说把X中的这个元素当前已经匹配的Y中的元素让出来,让给当前正在匹配的那个元素,而自己去寻找是否有其它的元素跟自己匹配,这样一直下去之后,就能达到最多的匹配的效果了。
1 #include<cstdio> 2 #include<cstring> 3 const int maxn = 500+3; 4 int map[maxn][maxn],visit[maxn],pipei[maxn],k,m,n,x,y; 5 6 int dfs(int x) { 7 for(int i = 1;i<=n;++i) 8 if(!visit[i] && map[x][i]) { 9 visit[i] = 1; 10 if(!pipei[i] || dfs(pipei[i])) { 11 pipei[i] = x; 12 return 1; 13 } 14 } 15 return 0; 16 } 17 18 int main() { 19 while(scanf("%d",&k),k) { 20 scanf("%d%d",&m,&n); 21 memset(map,0,sizeof(map)); 22 memset(pipei,0,sizeof(pipei)); 23 while(k--) { 24 scanf("%d%d",&x,&y); 25 map[x][y] = 1; //切不可加上map[y][x]也等于1 26 } 27 int tot = 0; 28 for(int i = 1;i<=m;++i) { 29 memset(visit,0,sizeof(visit)); 30 tot += dfs(i); 31 } 32 printf("%d ",tot); 33 } 34 return 0; 35 }