[关闭]
@ZCDHJ 2018-09-29T00:59:51.000000Z 字数 1763 阅读 601

Luogu2891 吃饭

网络流


Luogu

我们考虑将牛拆成两个点,来限制其享用食物或饮料的种类数(每头牛只能享用一种食物和饮料),然后对于每头牛喜爱的列表连边,再建立超级源,超级汇,最后跑一遍最大流就行啦。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <queue>
  5. const int INF = 0x3f3f3f3f;
  6. const int MAXN = 100;
  7. const int MAXM = MAXN * MAXN * 2 + MAXN * 3;
  8. int n, m, k, sp, ep, edge = -1;
  9. int firstEdge[MAXN * 4 + 2], curEdge[MAXN * 4 + 2], depth[MAXN * 4 + 2];
  10. struct Edge {
  11. int to, f, nxt;
  12. Edge(){}
  13. Edge(int x, int y, int z) {
  14. to = y;
  15. f = z;
  16. nxt = firstEdge[x];
  17. }
  18. } e[MAXM << 1 | 1];
  19. inline int read() {
  20. register int x = 0;
  21. register char ch = getchar();
  22. while(!isdigit(ch)) ch = getchar();
  23. while(isdigit(ch)) {
  24. x = x * 10 + ch - '0';
  25. ch = getchar();
  26. }
  27. return x;
  28. }
  29. inline void addEdge(int x, int y, int z) {
  30. e[++edge] = Edge(x, y, z);
  31. firstEdge[x] = edge;
  32. }
  33. bool getDepth() {
  34. std::queue <int> q;
  35. memset(depth, 0, sizeof(depth));
  36. depth[sp] = 1;
  37. q.push(sp);
  38. do {
  39. int from = q.front();
  40. q.pop();
  41. for(int k = firstEdge[from]; ~k; k = e[k].nxt) {
  42. int to = e[k].to, f = e[k].f;
  43. if(f > 0 && !depth[to]) {
  44. depth[to] = depth[from] + 1;
  45. q.push(to);
  46. }
  47. }
  48. } while(!q.empty());
  49. return depth[ep] > 0;
  50. }
  51. int Augment(int x, int flow) {
  52. if(x == ep) return flow;
  53. for(int &k = curEdge[x]; ~k; k = e[k].nxt) {
  54. int to = e[k].to, f = e[k].f;
  55. if(f > 0 && depth[to] == depth[x] + 1) {
  56. int tmp = Augment(to, std::min(flow, f));
  57. if(tmp > 0) {
  58. e[k].f -= tmp;
  59. e[k ^ 1].f += tmp;
  60. return tmp;
  61. }
  62. }
  63. }
  64. return 0;
  65. }
  66. int Dinic() {
  67. int res = 0, tmp;
  68. while(getDepth()) {
  69. for(int i = sp; i <= ep; ++i) curEdge[i] = firstEdge[i];
  70. while((tmp = Augment(sp, INF)) > 0) res += tmp;
  71. }
  72. return res;
  73. }
  74. int main() {
  75. n = read();
  76. m = read();
  77. k = read();
  78. sp = 0;
  79. ep = 2 * n + m + k + 1;
  80. memset(firstEdge, -1, sizeof(firstEdge));
  81. for(int i = 1; i <= n; ++i) {
  82. int tmp1 = read(), tmp2 = read(), tmp3;
  83. while(tmp1--) {
  84. tmp3 = read();
  85. addEdge(2 * n + tmp3, i, 1);
  86. addEdge(i, 2 * n + tmp3, 0);
  87. }
  88. addEdge(i, i + n, 1);
  89. addEdge(i + n, i, 0);
  90. while(tmp2--) {
  91. tmp3 = read();
  92. addEdge(i + n, tmp3 + 2 * n + m, 1);
  93. addEdge(tmp3 + 2 * n + m, i + n, 0);
  94. }
  95. }
  96. for(int i = 1; i <= m; ++i) {
  97. addEdge(sp, i + 2 * n, 1);
  98. addEdge(i + 2 * n, sp, 0);
  99. }
  100. for(int i = 1; i <= k; ++i) {
  101. addEdge(2 * n + m + i, ep, 1);
  102. addEdge(ep, 2 * n + m + i, 0);
  103. }
  104. printf("%d\n", Dinic());
  105. return 0;
  106. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注