poj 1149 PIGS(网络流 BFS 标号法)(困难)

来源:互联网 发布:php手机验证码 编辑:程序博客网 时间:2024/05/22 06:08

PIGS
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 18402 Accepted: 8373

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

代码:

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define INF 300000000#define MAXM 1000#define MAXN 100int s,t;//源点,汇点int cus[MAXN+2][MAXN+2];//N+2个结点之间的容量int flow[MAXN+2][MAXN+2];//结点之间的流量int i,j;void init(){    int M,N;    int num;    int k;    int house[MAXN];    int last[MAXN];    memset(last,0,sizeof(last));memset(cus,0,sizeof(cus));    scanf("%d%d",&M,&N);    s=0,t=N+1;    for(i=1;i<=M;i++)        scanf("%d",&house[i]);    for(i=1;i<=N;i++)    {        scanf("%d",&num);        for(j=0;j<num;j++)        {            scanf("%d",&k);            if(last[k]==0)                cus[s][i]=cus[s][i]+house[k];            else                cus[last[k]][i]=INF;            last[k]=i;        }        scanf("%d",&cus[i][t]);    }}void ford(){    int pre[MAXN+2];    int minflow[MAXN+2];    int queue[MAXN+2];    int qs,qe;    int v;  //当前检查的顶点    int p;    for(i=0;i<MAXN+2;i++)    {        for(j=0;j<MAXN+2;j++)            flow[i][j]=0;    }    minflow[0]=INF;    while(1)    {        for(i=0;i<MAXN+2;i++)        {            pre[i]=-2;        }        pre[0]=-1;        qs=0;queue[qs]=0;qe=1;        while(qs<qe && pre[t]==-2)        {            v=queue[qs];qs++;            for(i=0;i<t+1;i++)            {                if(pre[i]==-2 && (p=cus[v][i]-flow[v][i]))                {                    pre[i]=v;queue[qe]=i;qe++;                    minflow[i]=(minflow[v]<p)?minflow[v]:p;                }            }        }        if(pre[t]==-2) break;        for(i=pre[t],j=t;i!=-1;j=i,i=pre[i])        {            flow[i][j]=flow[i][j]+minflow[t];            flow[j][i]=-flow[i][j];        }    }    for(i=0,p=0;i<t;i++)    {        p=p+flow[i][t];    }    printf("%d\n",p);}int main(){    init();    ford();    return 0;}




0 0