<题目链接>

题目大意:
有一个养猪场,厂长没有钥匙,这个养猪场一共M个猪圈,N个顾客,每个顾客有一些猪圈的钥匙,每个顾客需要一些猪,问你厂长最多能卖多少猪?这里有个条件是,厂长可以在一个顾客买完后,调整没有锁门的猪圈中猪数量,比如,把几个猪圈中的猪全部转到一个猪圈内(这个条件会影响到后期建图),然后再关门,等下一个顾客。

解题分析:

首先根据题意,将这个问题抽象成一个朴素的模型,

因为这样建图,图中最多可能有$2+N+M+N*M (≈1e5)$个节点。在这样的图上跑网络流速度会很慢,我们可以通过合并一些等效的点来达到简化模型的目的。

规律 1.  如果几个结点的流量的来源完全相同,则可以把它们合并成一个。

规律 2.  如果几个结点的流量的去向完全相同,则可以把它们合并成一个。

规律 3.  如果从点 u 到点 v 有一条容量为∞的边,并且点 v 除了点 u 以外没有别的流量来源,则可以把这两个结点合并成一个。

具体简化过程见  >>>

简化后的图为:

因此,最终的建图方案就是:源点到所有第一个打开各个猪圈的人连上一条边,容量为这个猪圈的数量上限,然后,上一个打开这个猪圈的人向下一个打开这个猪圈的人连一条容量为无穷的边,最后,所有人向汇点连一条边,容量为他所能拿的猪数量的上限。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <queue>
  7. using namespace std;
  8.  
  9. typedef long long ll;
  10. const ll INF = 1e18;
  11. const int N = 1e3+;
  12.  
  13. template<typename T>
  14. inline void read(T&x){
  15. x=;int f=;char ch=getchar();
  16. while(ch<''||ch>''){ if(ch=='-')f=-;ch=getchar(); }
  17. while(ch>=''&&ch<=''){ x=x*+ch-'';ch=getchar(); }
  18. x*=f;
  19. }
  20. struct Dinic
  21. {
  22. struct edge{ int from,to;ll cap,flow; };
  23. vector<edge>es;
  24. vector<int>G[N];
  25. bool vis[N];
  26. int dist[N],iter[N];
  27. void init(int n){
  28. for(int i=; i<=n+; i++)G[i].clear();
  29. es.clear();
  30. }
  31. void addedge(int from,int to,ll cap){
  32. es.push_back((edge){from,to,cap,}); //将边存储的边表
  33. es.push_back((edge){to,from,,});
  34. int x=es.size();
  35. G[from].push_back(x-); //G[u][i]记录以u为顶点的第i条边的反边在es中的编号
  36. G[to].push_back(x-);
  37. }
  38. bool BFS(int s,int t){ //bfs将该图划分成分层图
  39. memset(vis,,sizeof(vis));
  40. queue <int> q;
  41. vis[s]=;
  42. dist[s]=;
  43. q.push(s);
  44. while(!q.empty()){
  45. int u=q.front();q.pop();
  46. for(int i=; i<G[u].size(); i++){
  47. edge &e=es[G[u][i]];
  48. if(!vis[e.to]&&e.cap>e.flow){
  49. vis[e.to]=;
  50. dist[e.to]=dist[u]+;
  51. q.push(e.to);
  52. }
  53. }
  54. }
  55. return vis[t];
  56. }
  57. int DFS(int u,int t,ll f){
  58. if(u==t||f==)return f;
  59. int lastflow=,d;
  60. for(int &i=iter[u]; i<G[u].size(); i++){
  61. edge &e=es[G[u][i]];
  62. if(dist[u]+==dist[e.to]&&(d=DFS(e.to,t,min(f,e.cap-e.flow)))>){
  63. e.flow+=d; //正边真实流量-d
  64. es[G[u][i]^].flow-=d; //反边真实流量+d
  65. lastflow+=d; //得到现在搜得的能够流入汇点的流量
  66. f-=d; //找到一条增广路之后,减去这条路的流量,然后继续从这个顶点的其它边开始寻找增广路
  67. if(f==)break;
  68. }
  69. }
  70. return lastflow;
  71. }
  72. int Maxflow(int s,int t){
  73. int flow=;
  74. while(BFS(s,t)){
  75. memset(iter,,sizeof(iter));
  76. int d=;
  77. while(d=DFS(s,t,INF))flow+=d;
  78. }
  79. return flow;
  80. }
  81. }dinic;
  82.  
  83. int n,m,st,ed,last[N],pig[N]; //last记录上一个打开对应猪圈的人
  84. int main(){
  85. read(m);read(n);st=;ed=n+;
  86. for(int i=;i<=m;i++) read(pig[i]);
  87. for(int i=;i<=n;i++){
  88. int k;read(k);
  89. while(k--){
  90. int x;read(x);
  91. if(!last[x]) dinic.addedge(st,i,pig[x]),last[x]=i; //如果是第一个打开该猪圈的人,就直接从源点向他连一条边
  92. else dinic.addedge(last[x],i,INF),last[x]=i; //如果这个猪圈已经被打开过了,就从上一个打开的人向他连一条边
  93. }
  94. ll cal;read(cal);
  95. dinic.addedge(i,ed,cal); //每个人向汇点连一条边,容量为他们能够拿的猪的上限
  96. }
  97. cout<<dinic.Maxflow(st,ed)<<endl;
  98. }

POJ 1149 PIGS 【最大流】的更多相关文章

  1. POJ 1149 - PIGS - [最大流构图]

    Time Limit: 1000MS Memory Limit: 10000K Description Mirko works on a pig farm that consists of M loc ...

  2. poj 1149 pigs ---- 最大流

    题意以及分析:http://ycool.com/post/zhhrrm6#rule3 主要是建图,简化图,然后在套最大流的模板. #include <iostream> #include& ...

  3. poj 1149 pigs(最大流)

    题目大意:迈克在农场工作,农场有 m 个猪舍,每个猪舍有若干只猪,但是迈克不能打开任何一间猪舍.有 n 个顾客前来购买,每个顾客有最大的购买数量,每个顾客可以购买某些猪舍的猪,且顾客可以打开这些猪舍, ...

  4. [poj] 1149 PIGS || 最大流经典题目

    原题 题目大意 给你m个猪圈以及每个猪圈里原来有多少头猪,先后给你n个人,每个人能打开一些猪圈并且他们最多想买Ki头猪,在每一个人买完后能将打开的猪圈中的猪顺意分配在这次打开猪圈里,在下一个人来之前 ...

  5. POJ 1149 PIGS(Dinic最大流)

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20738   Accepted: 9481 Description ...

  6. poj 1149 Pigs 网络流-最大流 建图的题目(明天更新)-已更新

    题目大意:是有M个猪圈,N个顾客,顾客要买猪,神奇的是顾客有一些猪圈的钥匙而主人MIRKO却没有钥匙,多么神奇?顾客可以在打开的猪圈购买任意数量的猪,只要猪圈里有足够数量的猪.而且当顾客打开猪圈后mi ...

  7. 网络流(最大流):POJ 1149 PIGS

    PIGS Time Limit: 1000ms Memory Limit: 10000KB This problem will be judged on PKU. 64-bit integer(整数) ...

  8. POJ 1149 PIGS(最大流)

    Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock an ...

  9. poj 1149 PIGS【最大流经典建图】

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18727   Accepted: 8508 Description ...

  10. poj 1149 PIGS(最大流经典构图)

    题目描述:迈克在一个养猪场工作,养猪场里有M 个猪圈,每个猪圈都上了锁.由于迈克没有钥匙,所以他不能打开任何一个猪圈.要买猪的顾客一个接一个来到养猪场,每个顾客有一些猪圈的钥匙,而且他们要买一定数量的 ...

随机推荐

  1. python学习日记(OOP——静态方法和类方法)

    classmethod 类方法在Python中使用比较少,类方法传入的第一个参数为cls,是类本身.并且,类方法可以通过类直接调用,或通过实例直接调用.但无论哪种调用方式,最左侧传入的参数一定是类本身 ...

  2. CRLF在过滤XSS语句后打Cookie方式

    看了很长时间的漏洞奖励计划,学到了不少骚姿势,我觉得这个姿势很不错,总结下写篇文章发出来.针对CRLF漏洞打cookie的方法. 这里不讲概念挖掘方式了,以实战为主: 阅读文章前先参考文章:http: ...

  3. vue---组件间通信

    vue中比较重要的就是组件了.而组件随处可复用的特性,使得组件通信非常重要.那么组件之间通讯方式有哪些呢? 第一种:父子组件通讯: 如果是 html页面 中全局注册的组件 和 实例中局部注册的组件 H ...

  4. python selenium简单安装及使用

    1.安装 pip install selenium 2.下载浏览器对应的Driver 链接地址:https://sites.google.com/a/chromium.org/chromedriver ...

  5. Python list和 np.Array 的转换关系

    一.List转String 1.str list转 string a_list = ["h","e","l","l",& ...

  6. SpringCloud笔记五:Feign

    目录 什么是Feign? 有了Ribbon我还要Feign干嘛? 新建consumer-feign 修改api项目 引入Maven文件 新建feign的接口 启动项目 报错 发泄发泄心情,一个段落 什 ...

  7. C#连接和操作Oracle数据

    最近业务需要读取远程Oracle数据库的数据,这里简单记录一下. 这里采用的是Oracle.ManagedDataAccess方式连接Oracle数据库,这种方式有几个优点:①不用安装Oracle客户 ...

  8. MyBatis # $区别

    方式一: <select id="getUserById" resultType="User" parameterType=”int”> SELEC ...

  9. Nginx模块

    模块概述 https://kb.cnblogs.com/page/98352/ Nginx模块工作原理概述 (Nginx本身支持多种模块,如HTTP模块.EVENT模块和MAIL模块,本文只讨论HTT ...

  10. webpack配置使用gif动图

    1. 下载npm包: npm install url-loader --save-dev 2. webpack.config.js中module  -> rules里添加: { test: /\ ...