首页 > 代码库 > POJ--1149--PIGS

POJ--1149--PIGS

PIGS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 16398 Accepted: 7347

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

为了节省时间,果断犯贱看别个的博客写的题意,妹的,天坑,啊,说半天都说不到点上

题意:老板有n个猪圈,每个猪圈都有自己初始化的猪的数量,都锁了的,有m个顾客1---n的顺序来买猪,每个人有A数量的钥匙,可以打开猪圈买猪,在每个猪圈里面买到的数量不多于这个猪圈里面的数量,每个顾客有一个最大购买量B,每次有顾客买完猪之后,老板可以在那个顾客解锁了的猪圈之间任意转移猪的数量,然后全部锁上,也就是说下一个顾客来的时候猪圈都重新锁上了,问老板可以卖出去的猪的最大量   (每个猪圈里面可以放无限头猪,老板对猪圈里面猪的数量的转移只会在每个顾客购买之后,而且允许转移的猪圈只有那个顾客所能解开的所有猪圈,也就是说顾客的钥匙会全部用来打开猪圈)


对于猪圈来说,只有买它里面的猪的顾客才会对它有影响,而每次对某猪圈的转移都只会对下一个有这个猪圈钥匙的顾客有影响,而转移过程中能相互转移的猪圈决定与上一个顾客所带的钥匙,由此可以得到一个方案,对于同一个猪圈,只连接第一个买它里面猪的顾客,后面的买这个猪圈里面猪的顾客都只去连接上一个购买此猪圈的顾客,这样就清楚了

做法:设立超级起点S和超级汇点T,S连接m个点,S到第x个点的边的权设为猪圈x中猪的初始数量,也就是说这个边代表的就是猪圈,另一端连接的是第一个买这个猪圈里面猪的顾客,对于其他买这个猪圈里面猪的顾客,都与他前一个买这个猪圈里面猪的顾客相连,边权设置无穷大,因为这猪圈之间转移量是无限的,最后每个顾客都连接T点,边权为这个顾客的最大买猪量,于是、、、你家的猪就卖完了- -!


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define Max 111
#define INF (1<<30)
using namespace std;
int map[Max][Max],vis[Max];//map【0:S点; 1~n:顾客; n+1:T点;】,vis【标记】
int r[Max],f[Max];r【路径最小流量】,f【前标】
void EK(int L)	//标准EK算法。。。不用注释了吧-.-!
{
    int i,j,k,l,flag,cur,sum=0;
    while(1)
    {
        memset(vis,0,sizeof(vis));
        memset(f,0,sizeof(f));
        queue<int> q;
        q.push(0);
        r[0]=INF;
        flag=1;
        while(q.size()&&flag)
        {
            cur=q.front();
            q.pop();
            for(i=1;i<=L;i++)
            {
                if(!vis[i]&&map[cur][i]>0)
                {
                    q.push(i);
                    vis[i]=1;
                    f[i]=cur;
                    r[i]=min(r[cur],map[cur][i]);
                    if(i==L){flag=0;break;}
                }
            }
        }
        if(flag)break;
        for(i=L;i!=0;i=f[i])
        {
            map[f[i]][i]-=r[L];
            map[i][f[i]]+=r[L];
        }
        sum+=r[L];
    }
    printf("%d\n",sum);
}
int main (void)
{
    int n,m,i,j,k,l,pig[1111],p[1111];
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(map,0,sizeof(map));	//地图初始化
        memset(p,0,sizeof(p));	//前一个买i猪圈里面猪的顾客,0表示还没有
        for(i=1;i<=m;i++)
        {
            scanf("%d",&pig[i]);//记录每个猪圈里面猪的初始量
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d",&l);
            while(l--&&scanf("%d",&k))	//输入每个钥匙
            {
                if(p[k]==0)	//如果还没有记录有人买k猪圈里面的猪
                {
                    map[0][i]+=pig[k];	//那么i就是第一个,连接S点
                    p[k]=i;	//并记录
                }else
                {
                    map[p[k]][i]=INF;	//不然把i和p[k]里面记录的前一个顾客连接
                    p[k]=i;	//把i标记为最近购买的顾客
                }
            }
            scanf("%d",&k);	//输入最大购买量
            map[i][n+1]=k;	//连接T点
        }
        EK(n+1);
    }
    return 0;
}

POJ--1149--PIGS