[关闭]
@sensitive-cs 2017-03-20T15:04:15.000000Z 字数 2806 阅读 805

CQUPT 二分图

题解


POJ1325
题意:
有两台机器A,B,A有n种模式,B有m种模式,任意一件产品,要么可以在A的x模式下,要么在B的y模式下完成。但是每次机器转换模式,都需要重启,问最少需要重启的次数。
思路:
最少需要重启多少次,既是最少用了多少种模式。因为有A,B两个,所以想到二分图,对于一个零件,就在x,y之间连边。求最少的点覆盖,就是求边的最大匹配(画图去理解)。需要注意的是含有0的就不需要连边了,因为最开始就是0模式,这个点就不需要算。匈牙利算法过。。。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. bool line[105][105];
  4. bool used[105];
  5. int g[105];
  6. int n,m,k;
  7. bool dfs(int x)
  8. {
  9. for (int i = 1;i < m;i++)
  10. {
  11. if (line[x][i] && !used[i])
  12. {
  13. used[i] = 1;
  14. if (g[i] == -1 || dfs(g[i]))
  15. {
  16. g[i] = x;
  17. return 1;
  18. }
  19. }
  20. }
  21. return 0;
  22. }
  23. int main()
  24. {
  25. while (scanf("%d",&n) != EOF && n)
  26. {
  27. memset(line,0,sizeof(line));
  28. memset(g,-1,sizeof(g));
  29. scanf("%d%d",&m,&k);
  30. for (int i = 0;i < k;i++)
  31. {
  32. int x,y;
  33. int t;
  34. scanf("%d%d%d",&t,&x,&y);
  35. line[x][y] = 1;
  36. }
  37. int ans = 0;
  38. for (int i = 1;i < n;i++)
  39. {
  40. memset(used,0,sizeof(used));
  41. if (dfs(i)) ans++;
  42. }
  43. printf("%d\n",ans);
  44. }
  45. return 0;
  46. }

poj2771:guardian of decency
题意:
有许多人要出去远足,老师为了防止互相谈恋爱,就提出四个条件,如果四个条件都不满足的人就不能一起,问有多少人可以出去。
卡住:
不知道如何建边,后来看了题解,知道了可以谈恋爱的人之间建边,那么我们要求的就是二分图的最大独立集,即每个点之间都没有相连的边,就保证了没有人可以谈恋爱。
注意:
我们选择建立无向图(有向图无法实现退流操作。。。),所以同一条边会匹配两次,这就是最后要把匹配数除以2的原因。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int n;
  4. struct pupil
  5. {
  6. int h;
  7. char se;
  8. char ms[105];
  9. char sp[105];
  10. };
  11. typedef struct pupil pp;
  12. pp stu[505];
  13. bool line[505][505];
  14. bool used[505];
  15. int g[505];
  16. int mabs(int x)
  17. {
  18. return x >= 0 ? x : -x;
  19. }
  20. bool dfs(int x)
  21. {
  22. for (int i = 0;i < n;i++)
  23. {
  24. if (line[x][i] && !used[i])
  25. {
  26. used[i] = true;
  27. if (g[i] < 0 || dfs(g[i]))
  28. {
  29. g[i] = x;
  30. return true;
  31. }
  32. }
  33. }
  34. return false;
  35. }
  36. int main()
  37. {
  38. int t;
  39. scanf("%d",&t);
  40. while (t--)
  41. {
  42. memset(stu,0,sizeof(stu));
  43. memset(line,0,sizeof(line));
  44. memset(g,-1,sizeof(g));
  45. memset(used,0,sizeof(used));
  46. scanf("%d",&n);
  47. for (int i = 0;i < n;i++)
  48. scanf("%d %c %s %s",&stu[i].h,&stu[i].se,stu[i].ms,stu[i].sp);
  49. for (int i = 0;i < n;i++)
  50. for (int j = 0;j < n;j++)
  51. {
  52. bool flag = 1;
  53. if (mabs(stu[i].h-stu[j].h) > 40)
  54. flag = 0;
  55. if (stu[i].se == stu[j].se)
  56. flag = 0;
  57. if (strcmp(stu[i].ms,stu[j].ms) != 0)
  58. flag = 0;
  59. if (strcmp(stu[i].sp,stu[j].sp) == 0)
  60. flag = 0;
  61. if (flag) line[i][j] = 1;
  62. }
  63. int ans = 0;
  64. for (int i = 0;i < n;i++)
  65. {
  66. memset(used,0,sizeof(used));
  67. if (dfs(i)) ans++;
  68. }
  69. ans = n - ans/2;
  70. printf("%d\n",ans);
  71. }
  72. return 0;
  73. }

HDU3829 cats vs doge
题意:
有m只狗,n只猫,p个学生,每个学生如果喜欢狗,那么他一定讨厌猫,反之亦然。现在要去掉某些猫狗,如果一个学生的喜欢的被保留并且不喜欢的被去掉,那么这个学生就是开心的。问有最多能有多少学生开心。
卡住:
不知道如何建图,后来搜了报告,知道我们如果是将有矛盾的学生连边,那么很合理的,就是求最大独立集,即求最多的人不矛盾。很合理。。。
思路:
匈牙利算法,双向图,还是一条边匹配了两次,所以最后要除以2.
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. bool line[505][505];
  4. int g[505];
  5. bool v[505];
  6. struct ch
  7. {
  8. char like[5];
  9. char disl[5];
  10. };
  11. typedef struct ch ch;
  12. ch chi[505];
  13. int n,m,p;
  14. bool dfs(int x)
  15. {
  16. for (int i = 1;i <= p;i++)
  17. {
  18. if (!v[i] && line[x][i])
  19. {
  20. v[i] = 1;
  21. if (g[i] < 0 || dfs(g[i]))
  22. {
  23. g[i] = x;
  24. return 1;
  25. }
  26. }
  27. }
  28. return 0;
  29. }
  30. int main()
  31. {
  32. while (scanf("%d%d%d",&n,&m,&p) != EOF)
  33. {
  34. memset(chi,0,sizeof(chi));
  35. memset(line,0,sizeof(line));
  36. memset(g,-1,sizeof(g));
  37. memset(v,0,sizeof(v));
  38. for (int i = 1;i <= p;i++)
  39. scanf("%s%s",chi[i].like,chi[i].disl);
  40. for (int i = 1;i <= p;i++)
  41. for (int j = 1;j <= p;j++)
  42. {
  43. if (strcmp(chi[i].disl,chi[j].like) == 0) line[i][j] = line[j][i] = 1;
  44. if (strcmp(chi[i].like,chi[j].disl) == 0) line[i][j] = line[j][i] = 1;
  45. }
  46. int ans = 0;
  47. for (int i = 1;i <= p;i++)
  48. {
  49. memset(v,0,sizeof(v));
  50. if (dfs(i)) ans++;
  51. }
  52. printf("%d\n",p - ans / 2);
  53. }
  54. return 0;
  55. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注