POJ 1149 PIGS 最大流

PIGS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 18255 Accepted: 8300

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
题意:养猪场有m个猪圈,麦克没有猪圈钥匙,所以他不能打开猪圈。买猪的顾客有一些猪圈的钥匙,他们来买猪时,会将他们所拥有钥匙的猪圈全部打开,这样麦克就能重新分配每个猪圈的猪数量,当顾客走的时候,就再次把所有门都锁上,每个猪圈容纳猪的数量都是没有限制的。现在知道所有顾客拥有钥匙的情况以及他们要买的猪的数量,需要怎么安排,才能使得销售数量最大。输入告诉每个猪圈起始猪数量,以及每个顾客拥有的钥匙编号和要买猪的数量。

分析:一个网络流的题目。关键在于构造一个容量网络。《图论算法理论、实现及应用》这本书上有很详细的网络流知识讲解。

#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define N 1009
#define INF 999999999
using namespace std;

int pre[N];
int cus[N][N];
int flow[N][N];
int pig[N];
int last[N];
int q[N*2];

int n,m;
int num,k;

int main()
{
    int m,n;
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1;i<=m;i++)
        scanf("%d",&pig[i]);

        memset(last,0,sizeof last);
        memset(cus,0,sizeof cus);

        int s=0,t=n+1;

        for(int i=1;i<=n;i++)
        {
            scanf("%d",&num);
            for(int j=0;j<num;j++)
            {
                scanf("%d",&k);
                if(last[k]==0)
                    cus[s][i]+=pig[k];
                else
                    cus[last[k]][i]=INF;//表示先last[k]拿过k猪圈的猪后i在拿
                    last[k]=i;
            }
            scanf("%d",&cus[i][t]);
        }

        for(int i=0;i<=n+2;i++)
            for(int j=0;j<=n+2;j++)
                flow[i][j]=0;

        while(1)//多次BFS进行增广
        {
            int mmin=INF;
            for(int i=0;i<=n+2;i++)
                pre[i]=-2;

            int qs=0,qe=1;
            pre[0]=-1;q[qs]=0;//从源点开始

            while(pre[t]==-2 && qs<qe)//找到一条增广路就更新一下
            {
                int v=q[qs++];
                for(int i=1;i<=t;i++)
                {
                    int p=cus[v][i]-flow[v][i];
                    if(pre[i]==-2 && p)
                    {
                        pre[i]=v;
                        q[qe++]=i;
                        mmin=min(mmin,p); //记录每次可增广的最小值
                    }
                }
            }

            if(pre[t]==-2) break;

            for(int i=pre[t],j=t; i!=-1; j=i,i=pre[i])
            {
                flow[i][j]+=mmin;
                flow[j][i]=-flow[i][j];
            }
        }

        int ans=0;
        for(int i=1;i<t;i++)
            ans+=flow[i][t];

        printf("%d\n",ans);

    }
    return 0;
}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值