首页 > 代码库 > POJ 1149 PIGS(Dinic最大流)

POJ 1149 PIGS(Dinic最大流)

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

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 33 1 102 1 2 22 1 3 31 2 6

Sample Output

7

 

 

题目链接:POJ 1149

题意:有M个猪圈,每一个猪圈有初始数量的猪,所有猪都是一样的,有N个人,每一个人有K把钥匙可以打开K个猪圈,对与被打开的猪圈可以进行重新分配猪的数量,每个人又有要买的猪的数量,每一个人按照输入的顺序进来购买,求最后所有人能买到的猪的最大个数。

解题思路:首先肯定是在源点连到每一个猪圈,容量为该猪圈的初始数量;然后把人连到汇点,容量为人要购买的头数,由于当前买的时候可能对应猪圈已经被重新分配过,因此不是从源点连过来,而是从上一个拥有这个猪圈的钥匙的人连过来一条容量为无穷大的边;若你是第一个开猪圈的人则要从猪圈连过来一条容量为无穷大的边。然后求源点到汇点的最大流即可。

代码:

#include <stdio.h>#include <iostream>#include <algorithm>#include <cstdlib>#include <sstream>#include <numeric>#include <cstring>#include <bitset>#include <string>#include <deque>#include <stack>#include <cmath>#include <queue>#include <set>#include <map>using namespace std;#define INF 0x3f3f3f3f#define LC(x) (x<<1)#define RC(x) ((x<<1)+1)#define MID(x,y) ((x+y)>>1)#define CLR(arr,val) memset(arr,val,sizeof(arr))#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);typedef pair<int, int> pii;typedef long long LL;const double PI = acos(-1.0);const int N = 1110;const int M = 110 + N + 110 * N + N;struct edge{    int to, nxt, cap;    edge(int To = 0, int Nxt = 0, int Cap = 0): to(To), nxt(Nxt), cap(Cap) {}};edge E[M << 1];int head[N], d[N], tot;int opened[N];void init(){    CLR(head, -1);    tot = 0;    CLR(opened, 0);}inline void add(int s, int t, int cap){    E[tot] = edge(t, head[s], cap);    head[s] = tot++;    E[tot] = edge(s, head[t], 0);    head[t] = tot++;}int bfs(int s, int t){    CLR(d, -1);    d[s] = 0;    queue<int>q;    q.push(s);    while (!q.empty())    {        int u = q.front();        q.pop();        for (int i = head[u]; ~i; i = E[i].nxt)        {            int v = E[i].to;            if (d[v] == -1 && E[i].cap > 0)            {                d[v] = d[u] + 1;                if (v == t)                    return 1;                q.push(v);            }        }    }    return ~d[t];}int dfs(int s, int t, int f){    if (s == t || !f)        return f;    int ret = 0;    for (int i = head[s]; ~i; i = E[i].nxt)    {        int v = E[i].to;        if (d[v] == d[s] + 1 && E[i].cap > 0)        {            int df = dfs(v, t, min(f, E[i].cap));            if (df > 0)            {                E[i].cap -= df;                E[i ^ 1].cap += df;                ret += df;                f -= df;                if (!f)                    break;            }        }    }    if (!ret)        d[s] = -1;    return ret;}int Dinic(int s, int t){    int ret = 0;    while (bfs(s, t))        ret += dfs(s, t, INF);    return ret;}int main(void){    int m, n, b, c, i, j, k, id;    while (~scanf("%d%d", &m, &n))    {        init();        int S = 0, T = n + m + 1;        for (i = 1; i <= m; ++i)        {            scanf("%d", &c);            add(S, i, c);        }        for (i = 1; i <= n; ++i)        {            scanf("%d", &k);            for (j = 0; j < k; ++j)            {                scanf("%d", &id);                if (!opened[id])                    add(id, m + i, INF);                else                    add(opened[id], m + i, INF);                opened[id] = m + i;            }            scanf("%d", &b);            add(m + i, T, b);        }        printf("%d\n", Dinic(S, T));    }    return 0;}

 

POJ 1149 PIGS(Dinic最大流)