POJ1149-PIGS

PIGS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 21699 Accepted: 9915

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



题意:一个农夫要把养殖的猪卖出去,现有m个猪圈,农夫自己没有猪圈的钥匙。现有n个客户要来买猪,每个客户手中有A把钥匙,分别表示成猪圈的编号,并且每个客户需要买一定的猪。这些客户依次过来(编号从小到大),打开他们能打开的猪圈,农夫可以选择如何将这些猪卖给每一个客户,只要头数不超过客户的需求即可。农夫在处理好每一笔交易后能够将打开的猪圈门之内的猪任意分配,并关上所有的猪圈。现在问农夫能够卖出最多的猪的数量

解题思路:建一个源点与汇点,将顾客看作节点,源点和每个猪圈的第一个顾客连边,边的权是开始时猪圈中猪的数目,顾客j紧跟在顾客i之后打开某个猪圈,则边<i,j>的权是无限大,每个顾客和汇点之间连边,边的权是顾客所希望购买的猪的数目

具体建图思路可以看https://wenku.baidu.com/view/0ad00abec77da26925c5b01c.html


#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <string>  
#include <algorithm>  
#include <cmath>  
#include <map>  
#include <set>  
#include <stack>  
#include <queue>  
#include <vector>  
#include <bitset>  
  
using namespace std;  
  
#define LL long long  
const int INF = 0x3f3f3f3f;  
#define MAXN 500    
  
struct node  
{  
    int u, v, next, cap;  
} edge[MAXN*MAXN];
int nt[MAXN], s[MAXN], d[MAXN], a[MAXN*2+10],vis[MAXN*2+10],mp[MAXN][MAXN];  
int cnt;  
  
void init()  
{  
    cnt = 0;  
    memset(s, -1, sizeof(s));  
}  
  
void add(int u, int v, int c)  
{  
    edge[cnt].u = u;  
    edge[cnt].v = v;  
    edge[cnt].cap = c;  
    edge[cnt].next = s[u];  
    s[u] = cnt++;  
    edge[cnt].u = v;  
    edge[cnt].v = u;  
    edge[cnt].cap = 0;  
    edge[cnt].next = s[v];  
    s[v] = cnt++;  
}  
  
bool BFS(int ss, int ee)  
{  
    memset(d, 0, sizeof d);  
    d[ss] = 1;  
    queue<int>q;  
    q.push(ss);  
    while (!q.empty())  
    {  
        int pre = q.front();  
        q.pop();  
        for (int i = s[pre]; ~i; i = edge[i].next)  
        {  
            int v = edge[i].v;  
            if (edge[i].cap > 0 && !d[v])  
            {  
                d[v] = d[pre] + 1;  
                q.push(v);  
            }  
        }  
    }  
    return d[ee];  
}  
  
int DFS(int x, int exp, int ee)  
{  
    if (x == ee||!exp) return exp;  
    int temp,flow=0;  
    for (int i = nt[x]; ~i ; i = edge[i].next, nt[x] = i)  
    {  
        int v = edge[i].v;  
        if (d[v] == d[x] + 1&&(temp = (DFS(v, min(exp, edge[i].cap), ee))) > 0)  
        {  
            edge[i].cap -= temp;  
            edge[i ^ 1].cap += temp;  
            flow += temp;  
            exp -= temp;  
            if (!exp) break;  
        }  
    }  
    if (!flow) d[x] = 0;  
    return flow;  
}  
  
int Dinic_flow(int ss, int ee)  
{  
    int ans = 0;  
    while (BFS(ss, ee))  
    {  
        for (int i = 0; i <= ee; i++) nt[i] = s[i];  
        ans+= DFS(ss, INF, ee);  
    }  
    return ans;  
}  
  
int main()  
{  
    int n, m;  
    while (~scanf("%d %d", &m, &n))  
    {  
        init();  
		for (int i = 1; i <= m; i++) scanf("%d", &a[i]);
		int k,x;
		memset(vis, 0, sizeof vis);
		memset(mp, 0, sizeof mp);
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &k);
			for (int j = 1; j <= k; j++)
			{
				scanf("%d", &x);
				if (vis[x]) mp[vis[x]][i] = INF;
				else mp[0][i] += a[x], vis[x] = i;
			}
			scanf("%d", &x);
			mp[i][n + 1] = x;
		}
		for (int i = 0; i <= n + 1; i++)
			for (int j = 0; j <= n + 1; j++)
				if (mp[i][j]) add(i, j, mp[i][j]);
		printf("%d\n", Dinic_flow(0,n+1));  
    }  
    return 0;  
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值