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

3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6

Sample Output

7

Source

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

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

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

错误的建图方法

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

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

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

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

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

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

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

#include <cstdio>
#include <cstring> inline int get_c(void)
{
static const int siz = ; static char buf[siz];
static char *head = buf + siz;
static char *tail = buf + siz; if (head == tail)
fread(head = buf, , siz, stdin); return *head++;
} inline int get_i(void)
{
register int ret = ;
register int neg = false;
register int bit = get_c(); for (; bit < ; bit = get_c())
if (bit == '-')neg ^= true; for (; bit > ; bit = get_c())
ret = ret * + bit - ; return neg ? -ret : ret;
} template <class T>
inline T min(T a, T b)
{
return a < b ? a : b;
} const int inf = 2e9;
const int maxn = ; int n, m;
int s, t;
int edges;
int hd[maxn];
int to[maxn];
int nt[maxn];
int fl[maxn]; inline void add(int u, int v, int f)
{ //printf("add %d %d %d\n", u, v, f);
nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
} int dep[maxn]; inline bool bfs(void)
{
static int que[maxn];
static int head, tail; memset(dep, , sizeof(dep));
head = , tail = ;
que[tail++] = s;
dep[s] = ; while (head != tail)
{
int u = que[head++], v;
for (int i = hd[u]; ~i; i = nt[i])
if (!dep[v = to[i]] && fl[i])
{
dep[v] = dep[u] + ;
que[tail++] = v;
}
} return dep[t] != ;
} int dfs(int u, int f)
{
if (u == t || !f)
return f; int used = , flow, v; for (int i = hd[u]; ~i; i = nt[i])
if (dep[v = to[i]] == dep[u] + && fl[i])
{
flow = dfs(v, min(f - used, fl[i])); used += flow;
fl[i] -= flow;
fl[i^] += flow; if (used == f)
return f;
} if (!used)
dep[u] = ; return used;
} inline int maxFlow(void)
{
int maxFlow = , newFlow; while (bfs())
while (newFlow = dfs(s, inf))
maxFlow += newFlow; return maxFlow;
} signed main(void)
{
n = get_i();
m = get_i(); s = , t = (n + ) * m + ; memset(hd, -, sizeof(hd)); for (int i = ; i <= n; ++i)
{
int pigs = get_i();
add(s, i, pigs);
} for (int i = ; i < m; ++i)
for (int j = ; j <= n; ++j)
add((n + )*(i - ) + j, (n + )*i + j, inf); for (int i = ; i <= m; ++i)
{
int k = get_i();
for (int j = ; j <= k; ++j)
{
int p = get_i();
add((n + )*(i - ) + p, (n + )*i, inf);
add((n + )*i, (n + )*i + p, inf);
}
add((n + )*i, t, get_i());
} printf("%d\n", maxFlow());
}

正确的建图方法

设置一个源点,向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),小菜一碟了。

 #include <cstdio>
#include <cstring> inline int get_c(void)
{
static const int siz = ; static char buf[siz];
static char *head = buf + siz;
static char *tail = buf + siz; if (head == tail)
fread(head = buf, , siz, stdin); return *head++;
} inline int get_i(void)
{
register int ret = ;
register int neg = false;
register int bit = get_c(); for (; bit < ; bit = get_c())
if (bit == '-')neg ^= true; for (; bit > ; bit = get_c())
ret = ret * + bit - ; return neg ? -ret : ret;
} template <class T>
inline T min(T a, T b)
{
return a < b ? a : b;
} const int inf = 2e9;
const int maxn = ; int n, m;
int s, t;
int edges;
int hd[maxn];
int to[maxn];
int nt[maxn];
int fl[maxn]; inline void add(int u, int v, int f)
{ //printf("add %d %d %d\n", u, v, f);
nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
} int dep[maxn]; inline bool bfs(void)
{
static int que[maxn];
static int head, tail; memset(dep, , sizeof(dep));
head = , tail = ;
que[tail++] = s;
dep[s] = ; while (head != tail)
{
int u = que[head++], v;
for (int i = hd[u]; ~i; i = nt[i])
if (!dep[v = to[i]] && fl[i])
{
dep[v] = dep[u] + ;
que[tail++] = v;
}
} return dep[t] != ;
} int dfs(int u, int f)
{
if (u == t || !f)
return f; int used = , flow, v; for (int i = hd[u]; ~i; i = nt[i])
if (dep[v = to[i]] == dep[u] + && fl[i])
{
flow = dfs(v, min(f - used, fl[i])); used += flow;
fl[i] -= flow;
fl[i^] += flow; if (used == f)
return f;
} if (!used)
dep[u] = ; return used;
} inline int maxFlow(void)
{
int maxFlow = , newFlow; while (bfs())
while (newFlow = dfs(s, inf))
maxFlow += newFlow; return maxFlow;
} int last[maxn]; signed main(void)
{
n = get_i();
m = get_i(); s = , t = n + m + ; memset(hd, -, sizeof(hd)); for (int i = ; i <= n; ++i)
add(s, i, get_i()), last[i] = i; for (int i = ; i <= m; ++i)
{
for (int j = get_i(), k; j--; )
k = get_i(), add(last[k], n + i, inf), last[k] = n + i;
add(n + i, t, get_i());
} printf("%d\n", maxFlow());
}

@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. js Form.elements[i]的使用实例

    function pdf(){    //一个html里面可能存在多个form,所以document.form[0]指的是第一个form,document.form[1]返回就是第二个form,如果没 ...

  2. JS+CSS3人物奔跑动画

    查看效果:http://hovertree.com/texiao/jquery/58/ 效果图: 代码: <!DOCTYPE html> <html> <head> ...

  3. JS高程5.引用类型(2)Array类型

    Array类型: ECMAScript数组的每一项可以保存任何类型的数据,数组的大小是可以动态调整的. 创建数组的基本方式: (1)使用Array构造函数 var color=new Array(); ...

  4. VBA 格式化字符串 - Format大全

    VBA 格式化字符串 VBA 的 Format 函数与工作表函数 TEXT 用法基本相同,但功能更加强大,许多格式只能用于VBA 的 Format 函数,而不能用于工作表函数 TEXT ,以下是本人归 ...

  5. iOS - NSMutableAttributedString富文本的实现

    NSMutableAttributedString继承于NSAttributedString(带属性的字符串)能够简单快速实现富文本的效果;不多说直接上效果图和代码,通俗易懂: (一)效果图: (二) ...

  6. QQ空间/朋友圈类界面的搭建

    类似于QQ空间的布局主要是在说说信息.点赞.回复三大部分的自适应布局上. 当我们需要搭建类似QQ空间.微信朋友圈的界面的时候,可做如下操作: 创建一个对应的model类: 创建一个对应model类的f ...

  7. OC泛型

    OC泛型 泛型是程序设计语言的一种特性,他主要是为了限制类型的,比如OC中的数组,你可以限制他里面装的是NSString类型,泛型的话JAVA和C++都有的,大家要是对泛型不了解的话可以去百度一下. ...

  8. T-SQL 转义select … like中的特殊字符(百分号)

    众所周知,T-SQL中LIKE运算符使用%符号表示通配符.很多时候可能需要查询包含有%的数据,比如需要查询字段coupon中含有5%的数据.那么如何使用已经有百分号(%)符号的LIKE搜索字符串呢? ...

  9. javascript函数的几种写法集合

    1.常规写法 function fnName(){ console.log("常规写法"); } 2.匿名函数,函数保存到变量里 var myfn = function(){ co ...

  10. 阿里云yum源安装

      1.先清理掉yum.repos.d下面的所有repo文件 [root@localhost yum.repos.d]# rm -rf * 2.下载repo文件  wget http://mirror ...