题目链接:

  http://poj.org/problem?id=3281

题目大意:

  有n头牛,f种食物,d种饮料,第i头牛喜欢fi种食物和di种饮料,每种食物或者饮料被一头牛选中后,就不能被其他的牛选了,问最多能满足多少头牛的要求?

解题思路:

  最大匹配问题,关键在于如何建图,可以虚构出来一个源点,一个汇点,一共需要f+d+2*n+2个点即可,建图为:源点—>食物—>牛—>牛—>饮料—> 汇点。把牛作为点拆开建图是为了让一头牛只对应一种饮料和一种食物,避免出现对应多种饮料或者多种食物的情况。

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <cmath>
  7. #include <queue>
  8. using namespace std;
  9.  
  10. #define maxn 0x3f3f3f3f
  11. #define N 410
  12. int map[N][N], Layer[N], s, e;
  13. bool visit[N];
  14. bool CountLayer();
  15. int Dinic ();
  16.  
  17. int main ()
  18. {
  19. int n, f, d, x, y, m;
  20. while (scanf ("%d %d %d", &n, &f, &d) != EOF)
  21. {
  22. s = , e = f + d + n + n + ;
  23. memset (map, , sizeof(map));
  24.  
  25. for (int i=; i<=f; i++)
  26. map[][i] = ;//食物和源点连线
  27.  
  28. for (int i=; i<=d; i++)
  29. map[i+f+*n][e] = ;//饮料和汇点链接
  30.  
  31. for (int i=; i<=n; i++)
  32. map[i+f][i+f+n] = ;//对应的牛和牛链接
  33.  
  34. for (int i=; i<=n; i++)
  35. {//建立牛和食物及饮料的关系
  36. int num = f + i;
  37. scanf ("%d %d", &x, &y);
  38. while (x --)
  39. {
  40. scanf ("%d", &m);
  41. map[m][num] = ;
  42. }
  43. while (y --)
  44. {
  45. scanf ("%d", &m);
  46. map[num + n][m+f+*n] = ;
  47. }
  48. }
  49. printf ("%d\n", Dinic());
  50. }
  51. return ;
  52. }
  53.  
  54. bool CountLayer()
  55. {
  56. deque <int> Q;
  57. memset (Layer, , sizeof(Layer));
  58. Layer[] = ;
  59. Q.push_back();
  60. while (!Q.empty())
  61. {
  62. int nd = Q.front();
  63. Q.pop_front();
  64. for (int i=s; i<=e; i++)
  65. {
  66. if (map[nd][i]> && !Layer[i])
  67. {
  68. Layer[i] = Layer[nd] + ;
  69. if (i == e)
  70. return true;
  71. else
  72. Q.push_back(i);
  73. }
  74. }
  75. }
  76. return false;
  77. }
  78.  
  79. int Dinic ()//Dinic模板
  80. {
  81. int maxnflow = , i;
  82. while (CountLayer())
  83. {
  84. deque<int>Q;
  85. memset (visit, , sizeof(visit));
  86. visit[] = ;
  87. Q.push_back();
  88. while (!Q.empty())
  89. {
  90. int nd = Q.back();
  91. if (nd != e)
  92. {
  93. for (i=; i<=e; i++)
  94. {
  95. if (map[nd][i]> && Layer[i] == Layer[nd]+ && !visit[i])
  96. {
  97. visit[i] = ;
  98. Q.push_back(i);
  99. break;
  100. }
  101. }
  102. if (i > e)
  103. Q.pop_back();
  104. }
  105. else
  106. {
  107. int minflow = maxn;
  108. int mv;
  109. for (i=; i<Q.size(); i++)
  110. {
  111. int ns = Q[i-];
  112. int ne = Q[i];
  113. if (map[ns][ne] < minflow)
  114. {
  115. minflow = map[ns][ne];
  116. mv = ns;
  117. }
  118. }
  119. maxnflow += minflow;
  120. for (i=; i<Q.size(); i++)
  121. {
  122. int ns = Q[i-];
  123. int ne = Q[i];
  124. map[ns][ne] -= minflow;
  125. map[ne][ns] += minflow;
  126. }
  127. while (!Q.empty() && Q.back() != mv)
  128. Q.pop_back();
  129. }
  130. }
  131. }
  132. return maxnflow;
  133. }

poj 3281 Dining (最大网络流)的更多相关文章

  1. POJ 3281 Dining (网络流)

    POJ 3281 Dining (网络流) Description Cows are such finicky eaters. Each cow has a preference for certai ...

  2. POJ 3281 Dining(网络流拆点)

    [题目链接] http://poj.org/problem?id=3281 [题目大意] 给出一些食物,一些饮料,每头牛只喜欢一些种类的食物和饮料, 但是每头牛最多只能得到一种饮料和食物,问可以最多满 ...

  3. poj 3281 Dining(网络流+拆点)

    Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 20052   Accepted: 8915 Descripti ...

  4. POJ 3281 Dining(网络流最大匹配)

    分析: 数学模型是三个集合A,B,C,(a,b,c)构成一个匹配.因为图一个点只能匹配一次,把a拆点a',a", 在可以匹配的点上连边,s - b - a' - a" - c - ...

  5. POJ 3281 Dining(最大流)

    POJ 3281 Dining id=3281" target="_blank" style="">题目链接 题意:n个牛.每一个牛有一些喜欢的 ...

  6. poj 3281 Dining 网络流-最大流-建图的题

    题意很简单:JOHN是一个农场主养了一些奶牛,神奇的是这些个奶牛有不同的品味,只喜欢吃某些食物,喝某些饮料,傻傻的John做了很多食物和饮料,但她不知道可以最多喂饱多少牛,(喂饱当然是有吃有喝才会饱) ...

  7. POJ 3281 Dining 网络流最大流

    B - DiningTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.ac ...

  8. poj 3281 Dining【拆点网络流】

    Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11828   Accepted: 5437 Descripti ...

  9. POJ 3281 Dining (网络流之最大流)

    题意:农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 100) 种饮料.每头牛都有各自喜欢的食物和饮料, 而每种食物或饮料只能分配给 ...

随机推荐

  1. Nexus3.0.1如何上传第三方插件

    原文:http://blog.csdn.net/wang465745776/article/details/52527905 前提条件 Nexus 3.0.1 提出问题 如何上传第三方插件到Nexus ...

  2. mysql中如何查询最近24小时、top n查询

    MySQL中如何查询最近24小时. where visittime >= NOW() - interval 1 hour; 昨天. where visittime between CURDATE ...

  3. CentOS 6.x Radius

    CentOS 6.x Radius 一.   实现环境: 1.系统:CentOS  release  6.6 (Final) 2.需要软件包: 1) freeradius-2.1.12-6.e16.x ...

  4. Office WORD如何取消开始工作右侧栏

    工具-选项-视图,取消勾选"启动任务窗格"  

  5. java克隆对象clone()的使用方法和作用

    转自:997.html">http://www.okrs.cn/blog/news/?997.html 内容摘要 若需改动一个对象,同一时候不想改变调用者的对象.就要制作该对象的一个本 ...

  6. HDU1542Atlantis(扫描线)

    HDU1542Atlantis(扫描线) 题目链接 题目大意:给你n个覆盖矩形,问最后覆盖的面积. 解题思路:将每一个矩形拆成两条线段,一条是+1的,还有一条是减1的.然后扫描先从上往下扫描,碰到加1 ...

  7. 【网站支付PHP篇】thinkPHP集成支付宝支付(担保交易)

    目录 系列说明 开发环境 部署支付宝 支付请求 支付宝返回处理 系列说明 最近在帮朋友的系统安装支付模块(兑换网站积分),现在总结一些开发心得,希望对大家有用.这个系列会讲以下第三方支付平台的集成: ...

  8. VS2010打开高版本VS解决方案

    http://blog.csdn.net/backspace110/article/details/62111273 Microsoft Visual Studio Solution File, Fo ...

  9. ubuntu中查看已安装软件包的方法

    ubuntu中查看已安装软件包的方法: 方法一:在新立得软件包管理器中,打到已安装,便可以看看有多少包被安装. 如果想把这些包的信息复制到一文件里,可用下面的方法. 方法二:在终端输入 sudo dp ...

  10. C中使用memset

    int i; cout<<memset(&i,1,sizeof(int))<<endl; 输出结果是16843009,而不是填充的1111 1111,为什么呢? 因为m ...