[关闭]
@Asuna 2017-02-23T13:37:30.000000Z 字数 1613 阅读 820

2016寒假集训队第六次作业(二分图)

题解


匈牙利算法

Problem A:COURSES

题意:求一个二分图的最大匹配。

题解:匈牙利算法求二分图最大匹配。

参考代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. int g[510][510],mat[510],t,n,m;
  6. bool used[510];
  7. bool dfs(int u)
  8. {
  9. for (int v=1; v<=g[0][1]; v++)
  10. {
  11. if (g[u][v] && !used[v])
  12. {
  13. used[v]=true;
  14. if (mat[v]==-1 || dfs(mat[v]))
  15. {
  16. mat[v]=u;
  17. return true;
  18. }
  19. }
  20. }
  21. return false;
  22. }
  23. int hungary()
  24. {
  25. int res=0;
  26. memset(mat,-1,sizeof(mat));
  27. for (int u=1; u<=g[0][0]; u++)
  28. {
  29. memset(used,0,sizeof(used));
  30. if(dfs(u)) res++;
  31. }
  32. return res;
  33. }
  34. int main()
  35. {
  36. cin>>t;
  37. while (t--)
  38. {
  39. memset(g,0,sizeof(g));
  40. cin>>g[0][0]>>g[0][1];
  41. for (int i=1; i<=g[0][0]; i++)
  42. {
  43. scanf("%d",&n);
  44. for (int j=0; j<n; j++)
  45. {
  46. scanf("%d",&m);
  47. g[i][m]=1;
  48. }
  49. }
  50. if (hungary()!=g[0][0])
  51. cout<<"NO"<<endl;
  52. else
  53. cout<<"YES"<<endl;
  54. }
  55. return 0;
  56. }

Problem B:The Accomodation of Students

题意:先判断一个图是不是二分图,如果是二分图则求其最大匹配。

题解: 判断是否为二分图的方法是染色,当一个结点有两种不同的颜色时,则该图必定不是二分图。最大匹配用的是匈牙利算法。

参考代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<queue>
  4. #include<cstring>
  5. using namespace std ;
  6. int a[500],pre[500],n,m,ans;
  7. bool vis[500],map[500][500];
  8. bool bfs()
  9. {
  10. queue<int> que;
  11. que.push(1);
  12. a[1]=1;
  13. while(!que.empty())
  14. {
  15. int now=que.front();
  16. que.pop();
  17. for (int i=1; i<=n; i++)
  18. {
  19. if (map[now][i])
  20. {
  21. if (a[now]==a[i]) return false;
  22. else if (a[i]==0)
  23. {
  24. a[i]=-a[now];
  25. que.push(i);
  26. }
  27. }
  28. }
  29. }
  30. return true;
  31. }
  32. int hungry(int pos)
  33. {
  34. for (int i=1; i<=n; i++)
  35. {
  36. if (!vis[i] && map[pos][i])
  37. {
  38. vis[i]=true ;
  39. if (pre[i]==-1 || hungry(pre[i]))
  40. {
  41. pre[i]=pos;
  42. return 1;
  43. }
  44. }
  45. }
  46. return 0;
  47. }
  48. int main()
  49. {
  50. while(cin>>n>>m)
  51. {
  52. memset(map,false,sizeof(map)) ;
  53. memset(pre,-1,sizeof(pre)) ;
  54. memset(a,0,sizeof(a)) ;
  55. for (int i=0; i<m; i++)
  56. {
  57. int x,y;
  58. scanf("%d%d",&x,&y);
  59. map[x][y]=true;
  60. }
  61. if (!bfs()) cout<<"No"<<endl;
  62. else
  63. {
  64. ans=0;
  65. for (int i=1; i<=n; i++)
  66. {
  67. memset(vis,false,sizeof(vis));
  68. ans+=hungry(i);
  69. }
  70. cout<<ans<<endl;
  71. }
  72. }
  73. return 0;
  74. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注