传送门:https://www.luogu.org/problemnew/show/P2891

题面

\

Solution

网络流

先引用一句真理:网络流最重要的就是建模

今天这道题让我深有体会

首先,观察数据范围,n=100,一般这种100-1000的图论题,很有可能是网络流.

那就直接从网络流的角度入手

考虑这样建模

建模要点如下:

1.建权值为1的边,保证每个食物和水仅用一次

 2.没了

对以上的图求一个最大流,那不就是我们想要的最大的匹配数吗?

看起来是不是很OjbK?

其实不然,这样子一头牛有可能脚踏N条食物和水,但是题目要求一头牛只能吃喝一次

反例如下:

所以说,我们要对一头牛吃的东西做一个限制,保证其只流过1

怎么限制呢?

直接把一头牛拆成两头牛,中间连一条边就OK了嘛

如下图:

接下来就可以考虑如何给点编号了

我的编号方法很直接,很暴力

源点:1

食物: 2 ~  2+f-1

牛   2+f ~ 2+f+2n -1

水: 2+f+2n ~ 2+f+2n+d

汇点:1000

如下图所示

按照以上方法,每种物品对应的点为:

食物i : 1+i

牛i : 1+f+i

牛i的右边的分点:  1+f+n+i

水i: 1+f+2*n+i

然后dinic直接求一波最大流就可以带走啦

DINIC教程传送门: http://www.cnblogs.com/SYCstudio/p/7260613.html (个人感觉写得很清楚)

Code

  1. //Luogu P2891 [USACO07OPEN]吃饭Dining
  2. //Apr,2ed,2018
  3. //Dinic求最大流
  4. #include<iostream>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<cstring>
  8. using namespace std;
  9. long long read()
  10. {
  11. long long x=0,f=1; char c=getchar();
  12. while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
  13. while(isdigit(c)){x=x*10+c-'0';c=getchar();}
  14. return x*f;
  15. }
  16. const int N=100+10;
  17. const int M=N*10;
  18. const int inf=0x3f3f3f3f;
  19. struct line
  20. {
  21. int t,rev,w;
  22. };
  23. vector <line> e[M];
  24. inline void AddLine(int s,int t)
  25. {
  26. line temp;
  27. temp.t=t,temp.rev=e[t].size(),temp.w=1;
  28. e[s].push_back(temp);
  29. temp.t=s,temp.rev=e[s].size()-1,temp.w=0;
  30. e[t].push_back(temp);
  31. }
  32. int n,f,d;
  33. int dl[M],head,tail,depth[M];
  34. bool visited[M];
  35. bool bfs()
  36. {
  37. memset(visited,0,sizeof visited);
  38. dl[1]=1,depth[1]=1;
  39. visited[1]=true;
  40. head=1,tail=2;
  41. while(head<tail)
  42. {
  43. int now=dl[head],size=e[now].size();
  44. for(int i=0;i<size;i++)
  45. if(visited[e[now][i].t]==false and e[now][i].w>0)
  46. {
  47. visited[e[now][i].t]=true;
  48. dl[tail++]=e[now][i].t;
  49. depth[e[now][i].t]=depth[now]+1;
  50. }
  51. head++;
  52. }
  53. return visited[1000];
  54. }
  55. int dfs(int now,int f)
  56. {
  57. if(now==1000)
  58. return f;
  59. int size=e[now].size(),ans=0;
  60. for(int i=0;i<size;i++)
  61. if(depth[e[now][i].t]==depth[now]+1 and e[now][i].w>0)
  62. {
  63. int t_ans=dfs(e[now][i].t,min(f,e[now][i].w));
  64. e[now][i].w-=t_ans;
  65. e[e[now][i].t][e[now][i].rev].w+=t_ans;
  66. f-=t_ans,ans+=t_ans;
  67. if(f==0) break;
  68. }
  69. return ans;
  70. }
  71. int Dinic()
  72. {
  73. int ans=0;
  74. while(bfs())
  75. ans+=dfs(1,inf);
  76. return ans;
  77. }
  78. int main()
  79. {
  80. n=read(),f=read(),d=read();
  81. for(int i=1;i<=1000;i++)
  82. e[i].reserve(16);
  83. for(int i=1;i<=f;i++)
  84. AddLine(1,1+i);
  85. for(int i=1;i<=d;i++)
  86. AddLine(1+f+2*n+i,1000);
  87. for(int i=1;i<=n;i++)
  88. {
  89. int F=read(),D=read(),temp;
  90. for(int j=1;j<=F;j++)
  91. {
  92. temp=read();
  93. AddLine(1+temp,1+f+i);
  94. }
  95. for(int j=1;j<=D;j++)
  96. {
  97. temp=read();
  98. AddLine(1+f+n+i,1+f+2*n+temp);
  99. }
  100. }
  101. for(int i=1;i<=n;i++)
  102. AddLine(1+f+i,1+f+n+i);
  103.  
  104. printf("%d",Dinic());
  105. return 0;
  106. }

C++

后记

写的时候发现自己真的有点生疏了,这种比较靠记忆的算法还是久不久搞一下来恢复记忆为妙

网络流的时间复杂度真玄学

[Luogu P2891/POJ 3281/USACO07OPEN ]吃饭Dining的更多相关文章

  1. 「洛谷P2891」[USACO07OPEN]吃饭Dining 解题报告

    P2891 [USACO07OPEN]吃饭Dining 题目描述 Cows are such finicky eaters. Each cow has a preference for certain ...

  2. P2891 [USACO07OPEN]吃饭Dining

    漂亮小姐姐点击就送:https://www.luogu.org/problemnew/show/P2891 题目描述 Cows are such finicky eaters. Each cow ha ...

  3. P2891 [USACO07OPEN]吃饭Dining(最大流+拆点)

    题目描述 Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she w ...

  4. P2891 [USACO07OPEN]吃饭Dining 最大流

    \(\color{#0066ff}{ 题目描述 }\) 有F种食物和D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料.现在有n头牛,每头牛都有自己喜欢的食物种类列表和饮料种类 ...

  5. 洛谷P2891 [USACO07OPEN]吃饭Dining

    题目描述 Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she w ...

  6. 洛谷 P2891 [USACO07OPEN]吃饭Dining

    裸的最大流. #include <cstdio> #include <cstring> #include <queue> const int MAXN = 4e3 ...

  7. [USACO07OPEN]吃饭Dining

    嘟嘟嘟 这应该是网络流入门题之一了,跟教辅的组成这道题很像. 把每一只牛看成书,然后对牛拆点,因为每一只牛只要一份,食物和饮料分别看成练习册和答案. #include<cstdio> #i ...

  8. bzoj1711[USACO07OPEN]吃饭Dining

    题意 有F种食物和D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料.现在有n头牛,每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享用到自己喜欢的食物和饮 ...

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

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

随机推荐

  1. Python-装饰器中保留被装饰函数元数据

     函数的元数据包括哪些呢? 1. 函数名 .__name__ 2. 函数注释 .__doc__ ... 那,如何保留被装饰函数元数据,通过wraps装饰器保留被装饰函数的元数据 import time ...

  2. 重启springboot

    前言:springboot项目开发时,会遇到项目重新启动的情况.在百度上资料比较零碎需要整理,实践时需要踩坑,自己在项目中已经实现的功能拿出来与大家分享.希望每一位coder能在编程的路上少走一些弯路 ...

  3. STM32CubeMX HAL库串口: 使用DMA数据发送、使用DMA不定长度数据接收

    转载自 https://blog.csdn.net/euxnijuoh/article/details/81638676

  4. SpringBoot-04-自动配置原理再理解

    4. 自动配置原理再理解 ​ 配置文件到底能写什么?怎么写?SpringBoot官方文档有大量的配置,但是难以全部记住. 分析自动配置原理 ​ 官方文档 ​ 我们以HttpEncodingAutoCo ...

  5. P3419 [POI2005]SAM-Toy Cars / SP688 SAM - Toy Cars

    一道很妙的贪心题 题面 我们考虑当我们插入时会面临的两种情况 当地上的玩具,不满 \(k\) 个时,那我们直接放就可以了. 当满了 \(k\) 个的时候,我们就要从地上拿出一个来给当前的腾位置. 这就 ...

  6. Vue自定义Popup弹窗组件|vue仿ios、微信弹窗|vue右键弹层

    基于vue.js构建的轻量级Vue移动端弹出框组件Vpopup vpopup 汇聚了有赞Vant.京东NutUI等Vue组件库的Msg消息框.Popup弹层.Dialog对话框.Toast弱提示.Ac ...

  7. 拜托,别再问我怎么自学 Java 了!和盘托出

    假如有那么残酷的一天,我不小心喝错了一瓶药,一下子抹掉了我这十多年的编程经验,把我变成了一只小白.我想自学 Java,并且想要找到一份工作,我预计需要 6 个月的时间,前提条件是每天都处于高效率的学习 ...

  8. Python+Appium自动化测试(3)-编写自动化脚本

    之前一篇博客已经讲述怎样手动使用appium-desktop启动测试机上的app,但我们实际跑自动化脚本的过程中,是需要用脚本调用appium启动app的,接下来就尝试写Python脚本启动app并登 ...

  9. centos7.5安装gcc7.2.0

    参考https://www.cnblogs.com/lazyInsects/p/9778910.html cd /usr/src wget https://mirrors.tuna.tsinghua. ...

  10. Redis安装使用以及可能的算法实践

    layout: post title: 2017-12-05-Redis 入门 tags: - Redis - 实时特征 - UCB, Tompson sampling Redis 是什么? Redi ...