POJ 1149 PIGS
PIGS
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 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的更多相关文章
- poj 1149 Pigs 网络流-最大流 建图的题目(明天更新)-已更新
题目大意:是有M个猪圈,N个顾客,顾客要买猪,神奇的是顾客有一些猪圈的钥匙而主人MIRKO却没有钥匙,多么神奇?顾客可以在打开的猪圈购买任意数量的猪,只要猪圈里有足够数量的猪.而且当顾客打开猪圈后mi ...
- POJ 1149 PIGS(Dinic最大流)
PIGS Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20738 Accepted: 9481 Description ...
- poj 1149 PIGS【最大流经典建图】
PIGS Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 18727 Accepted: 8508 Description ...
- 网络流(最大流):POJ 1149 PIGS
PIGS Time Limit: 1000ms Memory Limit: 10000KB This problem will be judged on PKU. 64-bit integer(整数) ...
- POJ 1149 - PIGS - [最大流构图]
Time Limit: 1000MS Memory Limit: 10000K Description Mirko works on a pig farm that consists of M loc ...
- POJ 1149 PIGS(最大流)
Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock an ...
- POJ 1149 PIGS (AC这道题很不容易啊)网络流
PIGS Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlo ...
- POJ 1149 PIGS 【网络流】
题意: m n //有m个猪圈,n个人卖猪. a1...am //编号为i的猪圈里有ai头猪. b1 c1...cb1 d1 //第i个人有bi把钥匙,分别是ci猪圈的,其它猪圈里的猪都 ...
- POJ 1149 PIGS ★(经典网络流构图)
[题意] 有M个猪圈,每个猪圈里初始时有若干头猪.一开始所有猪圈都是关闭的.依 次来了N个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪.每 个顾客分别都有他能够买的数量的上限.每个顾客走后, ...
随机推荐
- 生成Tab键或逗号分隔的CSV
<?php header("Content-type:text/csv;charset=utf-8"); header("Content-Disposition:a ...
- WEB项目会话集群的三种办法
web集群时session同步的3种方法 在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上, 如果session不同步的 ...
- 谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo
前言 前端已经过了单兵作战的时代了,现在一个稍微复杂一点的项目都需要几个人协同开发,一个战略级别的APP的话分工会更细,比如携程: 携程app = 机票频道 + 酒店频道 + 旅游频道 + ..... ...
- iOS调试通过UILocalNotification或RemoteNotification启动的app
相信很多同学都为调试苹果的通知烦恼过,特别是通过通知启动app这个功能,简直让人欲哭无泪!!! 然而我们都遇到的问题,苹果怎么可能没有想到,原来早就有了官方的解决办法,只是我们不知道而已... 这次又 ...
- 常见排序算法(附java代码)
常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
- js异步加载的3种方式(转载)
1.defer标签 只支持IE defer属性的定义和用法: 属性规定是否对脚本执行进行延迟,直到页面加载为止.有的 javascript 脚本 document.write 方法来创建当前的文 ...
- solr定时更新索引遇到的问题(SolrDataImportProperties Error loading DataImportScheduler properties java.lang.NullPointerException)
问题描述 报如下错误,很显然,问题原因:空指针异常: ERROR (localhost-startStop-1) [ ] o.a.s.h.d.s.SolrDataImportProperties ...
- [project euler] program 4
上一次接触 project euler 还是2011年的事情,做了前三道题,后来被第四题卡住了,前面几题的代码也没有保留下来. 今天试着暴力破解了一下,代码如下: (我大概是第 172,719 个解出 ...
- 什么是JS事件冒泡?
什么是JS事件冒泡?: 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理 程序或者事件返回true,那么 ...
- uploadify插件Http Error(302)错误记录(MVC)
由于项目(asp.net MVC)需要做一个附件上传的功能,使用的是jQuery的Uploadify插件的2.1.0版本,上传文件到自己项目指定的文件夹下面.做完之后,在谷歌上测试是正确的,在火狐上报 ...