二分图最大匹配匈牙利算法(poj)3041(模板)

喜欢ヅ旅行 2022-08-27 04:55 361阅读 0赞

给出一个图G=(V,E)

概念:

匹配:在图G中两两没有公共端点的边的集合

最大匹配:选出尽量多的边,使得任意两条选中的边均没有公共端点。

边覆盖:G中的任意顶点都至少是F中某条边的端点的边的集合

最小边覆盖:选出尽量少的边,使得G中的任意顶点都至少是选出的边的某个端点。

顶点覆盖:在图G中的任意边都有至少一个端点属于S的顶点集合。

最小顶点覆盖:选出尽量少的顶点,使得图G中的任意边都有至少一个端点属于S的顶点集合。

独立集:在G中两两互不相连的顶点集合。

最大独立集:选出尽量多的顶点,使得在G中两两互不相连、

定义:对于不存在独立点的图, 最大匹配 + 最小边覆盖 = E(所有边的集合)

定义:最大独立集 + 最小点集覆盖 = V(所有顶点集合)

定义:在二分图中,最大匹配 = 最小点集覆盖

二分图最大匹配:http://blog.csdn.net/y990041769/article/details/8812042

算法思想:从所有点出发,如果某个点还没有匹配,找与之相连的另一边没有匹配的点,如果都匹配了,那么找看能不能让其他的点增广到另一个点,把当前点让出来给这个点。

邻接表模板:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <vector>
  6. using namespace std;
  7. const int N = 1100;
  8. int V,m;
  9. int match[N];
  10. vector<int> map[N];
  11. bool used[N];
  12. void add_edge(int u,int v)
  13. {
  14. map[u].push_back(v);
  15. map[v].push_back(u);
  16. }
  17. bool dfs(int v)
  18. {
  19. used[v]=true;
  20. for(int i=0;i<map[v].size();i++)
  21. {
  22. int u=map[v][i],w=match[u];
  23. if(w<0 || !used[w]&&dfs(w))
  24. {
  25. match[v]=u;
  26. match[u]=v;
  27. return true;
  28. }
  29. }
  30. return false;
  31. }
  32. int bipartite_matchint()
  33. {
  34. int res=0;
  35. memset(match,-1,sizeof(match));
  36. for(int v=0;v<V;v++)
  37. {
  38. if(match[v]<0){
  39. memset(used,0,sizeof(used));
  40. if(dfs(v))
  41. res++;
  42. }
  43. }
  44. return res;
  45. }
  46. int main()
  47. {
  48. int n;
  49. while(~scanf("%d%d",&n,&m))
  50. {
  51. V=2*n;
  52. for(int i=0;i<m;i++){
  53. int x,y;
  54. scanf("%d%d",&x,&y);
  55. add_edge(x,n+y);
  56. }
  57. printf("%d\n",bipartite_matchint());
  58. }
  59. return 0;
  60. }

邻接矩阵模板:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int N = 1100;
  6. int n,m;
  7. int link[N],vis[N],map[N][N];
  8. bool dfs(int x)
  9. {
  10. for(int i=1; i<=n; i++)
  11. {
  12. if(map[x][i]==1 && vis[i]==0)
  13. {
  14. vis[i]=1;
  15. if(link[i]==0 || dfs(link[i]))
  16. {
  17. link[i]=x;
  18. return true;
  19. }
  20. //vis[i]=0; //搞不懂加上这个会超时
  21. }
  22. }
  23. return false;
  24. }
  25. int bipartite_link() //求最大匹配
  26. {
  27. memset(link,0,sizeof(link));
  28. int count=0;
  29. for(int i=1; i<=n; i++)
  30. {
  31. memset(vis,0,sizeof(vis));
  32. if(dfs(i))
  33. count++;
  34. }
  35. return count;
  36. }
  37. int main()
  38. {
  39. while(~scanf("%d%d",&n,&m))
  40. {
  41. memset(map,0,sizeof(map));
  42. for(int i=0; i<m; i++)
  43. {
  44. int x,y;
  45. scanf("%d%d",&x,&y);
  46. map[x][y]=1;
  47. }
  48. printf("%d\n",bipartite_link());
  49. }
  50. return 0;
  51. }

发表评论

表情:
评论列表 (有 0 条评论,361人围观)

还没有评论,来说两句吧...

相关阅读