PIGS
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 20579   Accepted: 9387

Description

Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock any pighouse because he doesn't have the keys. Customers come to the farm one after another. Each of them has keys to some pig-houses and wants to buy a certain number of pigs. 
All data concerning customers planning to visit the farm on that particular day are available to Mirko early in the morning so that he can make a sales-plan in order to maximize the number of pigs sold. 
More precisely, the procedure is as following: the customer arrives, opens all pig-houses to which he has the key, Mirko sells a certain number of pigs from all the unlocked pig-houses to him, and, if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses. 
An unlimited number of pigs can be placed in every pig-house. 
Write a program that will find the maximum number of pigs that he can sell on that day.

Input

The first line of input contains two integers M and N, 1 <= M <= 1000, 1 <= N <= 100, number of pighouses and number of customers. Pig houses are numbered from 1 to M and customers are numbered from 1 to N. 
The next line contains M integeres, for each pig-house initial number of pigs. The number of pigs in each pig-house is greater or equal to 0 and less or equal to 1000. 
The next N lines contains records about the customers in the following form ( record about the i-th customer is written in the (i+2)-th line): 
A K1 K2 ... KA B It means that this customer has key to the pig-houses marked with the numbers K1, K2, ..., KA (sorted nondecreasingly ) and that he wants to buy B pigs. Numbers A and B can be equal to 0.

Output

The first and only line of the output should contain the number of sold pigs.

Sample Input

  1. 3 3
  2. 3 1 10
  3. 2 1 2 2
  4. 2 1 3 3
  5. 1 2 6

Sample Output

  1. 7

Source

[Submit]   [Go Back]   [Status]   [Discuss]

网络流——流量传递类型。

四月份的时候曾经写过一遍,但是已然忘光了,所以只得重新来过。

错误的建图方法

看到题之后有个简单的建图想法,就是设立M*N个猪圈点,以及N个商人点,如下建图:

源点向第一排M个猪圈点连容量为初始猪数目的边,代表一开始猪圈中最多存在的猪。

每排M个猪圈点中,A个能被打开的猪圈点向商人点连容量为无穷的边,代表可以被打开。

每排的商人点向汇点连容量为商人购买数目B的边,表示这个人的最大购买限度。

每排的商人点向下一排的A个点(这A个点还是本排商人能打开的猪圈)连无穷边,代表猪可以自由转移。

当然,因为猪也可以待在猪圈里不动,所以每排的各个猪圈向下一排的该猪圈连无穷边。

这样跑最大流,显然可以得到最优解,但是点的数量是O(N*M)的,而边的数量是……(懒得想了),果不其然地TLE了。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. inline int get_c(void)
  5. {
  6. static const int siz = ;
  7.  
  8. static char buf[siz];
  9. static char *head = buf + siz;
  10. static char *tail = buf + siz;
  11.  
  12. if (head == tail)
  13. fread(head = buf, , siz, stdin);
  14.  
  15. return *head++;
  16. }
  17.  
  18. inline int get_i(void)
  19. {
  20. register int ret = ;
  21. register int neg = false;
  22. register int bit = get_c();
  23.  
  24. for (; bit < ; bit = get_c())
  25. if (bit == '-')neg ^= true;
  26.  
  27. for (; bit > ; bit = get_c())
  28. ret = ret * + bit - ;
  29.  
  30. return neg ? -ret : ret;
  31. }
  32.  
  33. template <class T>
  34. inline T min(T a, T b)
  35. {
  36. return a < b ? a : b;
  37. }
  38.  
  39. const int inf = 2e9;
  40. const int maxn = ;
  41.  
  42. int n, m;
  43. int s, t;
  44. int edges;
  45. int hd[maxn];
  46. int to[maxn];
  47. int nt[maxn];
  48. int fl[maxn];
  49.  
  50. inline void add(int u, int v, int f)
  51. { //printf("add %d %d %d\n", u, v, f);
  52. nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
  53. nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
  54. }
  55.  
  56. int dep[maxn];
  57.  
  58. inline bool bfs(void)
  59. {
  60. static int que[maxn];
  61. static int head, tail;
  62.  
  63. memset(dep, , sizeof(dep));
  64. head = , tail = ;
  65. que[tail++] = s;
  66. dep[s] = ;
  67.  
  68. while (head != tail)
  69. {
  70. int u = que[head++], v;
  71. for (int i = hd[u]; ~i; i = nt[i])
  72. if (!dep[v = to[i]] && fl[i])
  73. {
  74. dep[v] = dep[u] + ;
  75. que[tail++] = v;
  76. }
  77. }
  78.  
  79. return dep[t] != ;
  80. }
  81.  
  82. int dfs(int u, int f)
  83. {
  84. if (u == t || !f)
  85. return f;
  86.  
  87. int used = , flow, v;
  88.  
  89. for (int i = hd[u]; ~i; i = nt[i])
  90. if (dep[v = to[i]] == dep[u] + && fl[i])
  91. {
  92. flow = dfs(v, min(f - used, fl[i]));
  93.  
  94. used += flow;
  95. fl[i] -= flow;
  96. fl[i^] += flow;
  97.  
  98. if (used == f)
  99. return f;
  100. }
  101.  
  102. if (!used)
  103. dep[u] = ;
  104.  
  105. return used;
  106. }
  107.  
  108. inline int maxFlow(void)
  109. {
  110. int maxFlow = , newFlow;
  111.  
  112. while (bfs())
  113. while (newFlow = dfs(s, inf))
  114. maxFlow += newFlow;
  115.  
  116. return maxFlow;
  117. }
  118.  
  119. signed main(void)
  120. {
  121. n = get_i();
  122. m = get_i();
  123.  
  124. s = , t = (n + ) * m + ;
  125.  
  126. memset(hd, -, sizeof(hd));
  127.  
  128. for (int i = ; i <= n; ++i)
  129. {
  130. int pigs = get_i();
  131. add(s, i, pigs);
  132. }
  133.  
  134. for (int i = ; i < m; ++i)
  135. for (int j = ; j <= n; ++j)
  136. add((n + )*(i - ) + j, (n + )*i + j, inf);
  137.  
  138. for (int i = ; i <= m; ++i)
  139. {
  140. int k = get_i();
  141. for (int j = ; j <= k; ++j)
  142. {
  143. int p = get_i();
  144. add((n + )*(i - ) + p, (n + )*i, inf);
  145. add((n + )*i, (n + )*i + p, inf);
  146. }
  147. add((n + )*i, t, get_i());
  148. }
  149.  
  150. printf("%d\n", maxFlow());
  151. }

正确的建图方法

设置一个源点,向M个猪圈点连初始数目的边,代表一开始的猪的数目。

然后想办法简化猪圈之间的转移,着重商人能得到的猪的来源,考虑直接在商人之间进行转移。

易知,如果商人X和商人Y,有X比Y先来,且X和Y有公共的猪圈的钥匙,那么Y能享受X能到达的所有猪圈。

用last_i表示上一个可以打开i猪圈的点,初始last_i=i猪圈初始点。

一个商人,如果有猪圈k的钥匙,那么last_k的所有流量都可以向这个商人转移,所有从last_k向商人连边,同时把last_k设为该商人。

商人点向汇点连最大购买数量的边。

跑最大流即可,点数O(N+M),边数O(N+M),小菜一碟了。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. inline int get_c(void)
  5. {
  6. static const int siz = ;
  7.  
  8. static char buf[siz];
  9. static char *head = buf + siz;
  10. static char *tail = buf + siz;
  11.  
  12. if (head == tail)
  13. fread(head = buf, , siz, stdin);
  14.  
  15. return *head++;
  16. }
  17.  
  18. inline int get_i(void)
  19. {
  20. register int ret = ;
  21. register int neg = false;
  22. register int bit = get_c();
  23.  
  24. for (; bit < ; bit = get_c())
  25. if (bit == '-')neg ^= true;
  26.  
  27. for (; bit > ; bit = get_c())
  28. ret = ret * + bit - ;
  29.  
  30. return neg ? -ret : ret;
  31. }
  32.  
  33. template <class T>
  34. inline T min(T a, T b)
  35. {
  36. return a < b ? a : b;
  37. }
  38.  
  39. const int inf = 2e9;
  40. const int maxn = ;
  41.  
  42. int n, m;
  43. int s, t;
  44. int edges;
  45. int hd[maxn];
  46. int to[maxn];
  47. int nt[maxn];
  48. int fl[maxn];
  49.  
  50. inline void add(int u, int v, int f)
  51. { //printf("add %d %d %d\n", u, v, f);
  52. nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
  53. nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
  54. }
  55.  
  56. int dep[maxn];
  57.  
  58. inline bool bfs(void)
  59. {
  60. static int que[maxn];
  61. static int head, tail;
  62.  
  63. memset(dep, , sizeof(dep));
  64. head = , tail = ;
  65. que[tail++] = s;
  66. dep[s] = ;
  67.  
  68. while (head != tail)
  69. {
  70. int u = que[head++], v;
  71. for (int i = hd[u]; ~i; i = nt[i])
  72. if (!dep[v = to[i]] && fl[i])
  73. {
  74. dep[v] = dep[u] + ;
  75. que[tail++] = v;
  76. }
  77. }
  78.  
  79. return dep[t] != ;
  80. }
  81.  
  82. int dfs(int u, int f)
  83. {
  84. if (u == t || !f)
  85. return f;
  86.  
  87. int used = , flow, v;
  88.  
  89. for (int i = hd[u]; ~i; i = nt[i])
  90. if (dep[v = to[i]] == dep[u] + && fl[i])
  91. {
  92. flow = dfs(v, min(f - used, fl[i]));
  93.  
  94. used += flow;
  95. fl[i] -= flow;
  96. fl[i^] += flow;
  97.  
  98. if (used == f)
  99. return f;
  100. }
  101.  
  102. if (!used)
  103. dep[u] = ;
  104.  
  105. return used;
  106. }
  107.  
  108. inline int maxFlow(void)
  109. {
  110. int maxFlow = , newFlow;
  111.  
  112. while (bfs())
  113. while (newFlow = dfs(s, inf))
  114. maxFlow += newFlow;
  115.  
  116. return maxFlow;
  117. }
  118.  
  119. int last[maxn];
  120.  
  121. signed main(void)
  122. {
  123. n = get_i();
  124. m = get_i();
  125.  
  126. s = , t = n + m + ;
  127.  
  128. memset(hd, -, sizeof(hd));
  129.  
  130. for (int i = ; i <= n; ++i)
  131. add(s, i, get_i()), last[i] = i;
  132.  
  133. for (int i = ; i <= m; ++i)
  134. {
  135. for (int j = get_i(), k; j--; )
  136. k = get_i(), add(last[k], n + i, inf), last[k] = n + i;
  137. add(n + i, t, get_i());
  138. }
  139.  
  140. printf("%d\n", maxFlow());
  141. }

@Author: YouSiki

POJ 1149 PIGS的更多相关文章

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

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

  2. POJ 1149 PIGS(Dinic最大流)

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

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

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

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

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

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

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

  6. POJ 1149 PIGS(最大流)

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

  7. POJ 1149 PIGS (AC这道题很不容易啊)网络流

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

  8. POJ 1149 PIGS 【网络流】

    题意: m n   //有m个猪圈,n个人卖猪. a1...am    //编号为i的猪圈里有ai头猪. b1 c1...cb1 d1   //第i个人有bi把钥匙,分别是ci猪圈的,其它猪圈里的猪都 ...

  9. POJ 1149 PIGS ★(经典网络流构图)

    [题意] 有M个猪圈,每个猪圈里初始时有若干头猪.一开始所有猪圈都是关闭的.依 次来了N个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪.每 个顾客分别都有他能够买的数量的上限.每个顾客走后, ...

随机推荐

  1. atitit.日期,星期,时候的显示方法ISO 8601标准

    atitit.日期,星期,时候的显示方法ISO 8601标准 1. ISO 86011 2. DAte日期的显示1 2.1. Normal1 2.2. 顺序日期表示法(可以将一年内的天数直接表示)1 ...

  2. echarts学习总结

    ECharts学习总结使用步骤1 引入ECharts <script src="echarts.min.js"></script>2 绘制一个简单的图表 为 ...

  3. 安装pip

    1. 安装pip. 我们同样需要在Python的官网上去下载,下载地址是: https://pypi.python.org/pypi/pip#downloads 2. 解压. 解压pip-9.0.1. ...

  4. CartO

    Carto documentation The following is a list of properties provided in CartoCSS that you can apply to ...

  5. iOS系统分析(二)Mach-O二进制文件解析

    ➠更多技术干货请戳:听云博客 0x01  Mach-O格式简单介绍 Mach-O文件格式是 OS X 与 iOS 系统上的可执行文件格式,类似于windows的 PE 文件 与 Linux(其他 Un ...

  6. grunt-笔记

    package.json: { "name": "grunt-uglify", "version": "1.0.0", ...

  7. 感受C# 的魅力,将一坨代码写成一行

    摘自MSDN :https://msdn.microsoft.com/zh-cn/library/bb549151(v=vs.100).aspx 1.平时定义一个委托 using System; // ...

  8. ASP.NET MVC 身份认证

    身份认证的好处就是, 如果这个页面没有登录, 刷新后会自动跳到登录页要求登录,保证了应用程序的安全.而Forms 身份认证是web下最常用的,如何配置呢?见下(基于mvc 4) 1.在webconfi ...

  9. ORA-00600 3020 ORA-10567案例

    PlateSpin克隆复制出的Oracle数据库服务器,往往启动数据库实例都会遇到一些杂七杂八的问题.今天测试DR环境时又遇到了一个特殊场景,在此之前,我已经遇到了下面两起案例: ORA-00600: ...

  10. JSON-RPC 2.0 规范中文文档

    链接地址如下 http://wiki.geekdream.com/Specification/json-rpc_2.0.html