[关闭]
@Chilling 2017-02-16T17:54:13.000000Z 字数 1720 阅读 966

HDU-2063: 过山车(匈牙利算法+最大匹配)

二分图


Description

RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?

Input

输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。。接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。

Output

对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。

Sample Input

6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0

Sample Output

3

二分图的最大匹配:最大匹配是具有最多边的匹配。我们使用匈牙利算法来找到最大匹配。

匈牙利算法:这个算法说白了就是最大流的算法,核心问题是找增广路径,它的基本模式就是:

  • 初始时最大匹配为空
  • while 找得到增广路径
    • do 把增广路径加入到最大匹配中去
  1. int match(int i)
  2. {
  3. int l=v[i].size(); //该女生可以匹配的男生个数
  4. for(int j=0;j<l;j++) //vector的编号从0到l-1
  5. {
  6. if(vis[v[i][j]]==1) //该男生已经被匹配过
  7. continue;
  8. vis[v[i][j]]=1;
  9. if(p[v[i][j]]==-1||match(p[v[i][j]])) //如果没有女生和这个男生匹配或者有更优的匹配
  10. {
  11. p[v[i][j]]=i; //将这个男生和女生匹配
  12. return 1;
  13. }
  14. }
  15. return 0;
  16. }

ans函数

  1. int ans()
  2. {
  3. int i;
  4. sum=0;
  5. for(i=1;i<=m;i++)
  6. {
  7. memset(vis,0,sizeof(vis)); //每次都初始化vis数组,假设所有都可以匹配,来找到最大的匹配数量
  8. if(match(i)==1) //判断该女生是否可以匹配到一个没有匹配过的男生或者有其他更优的选择(存在增广路径)
  9. sum++;
  10. }
  11. return sum;
  12. }
  1. #include<stdio.h>
  2. #include<vector>
  3. #include<string.h>
  4. using namespace std;
  5. int m,n,vis[555],p[555],sum;
  6. vector<int>v[555];
  7. int match(int i)
  8. {
  9. int l=v[i].size(); //该女生可以匹配的男生个数
  10. for(int j=0;j<l;j++) //从0到l-1
  11. {
  12. if(vis[v[i][j]]==1) //该男生已经被匹配过
  13. continue;
  14. vis[v[i][j]]=1;
  15. if(p[v[i][j]]==-1||match(p[v[i][j]])) //如果没有女生和这个男生匹配或者有更优的匹配
  16. {
  17. p[v[i][j]]=i; //将这个男生和女生匹配
  18. return 1;
  19. }
  20. }
  21. return 0;
  22. }
  23. int ans()
  24. {
  25. int i;
  26. sum=0;
  27. for(i=1;i<=m;i++)
  28. {
  29. memset(vis,0,sizeof(vis));
  30. if(match(i)==1)
  31. sum++;
  32. }
  33. return sum;
  34. }
  35. int main()
  36. {
  37. int k,x,y;
  38. while(scanf("%d",&k),k)
  39. {
  40. memset(p,-1,sizeof(p));
  41. scanf("%d%d",&m,&n);
  42. while(k--)
  43. {
  44. scanf("%d%d",&x,&y);
  45. v[x].push_back(y); //每个女生对应的所有男生
  46. }
  47. printf("%d\n",ans());
  48. for(int i=0;i<=m;i++)
  49. v[i].clear();
  50. }
  51. return 0;
  52. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注