poj1149 PIGS

PIGS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 13677 Accepted: 6044

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
 
    這題難點在於如何建圖,如何理解題目中的“if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses.”也將成爲建圖的關鍵。
    如果我們把每個顧客作爲圖中的點,則對於擁有某個豬圈的鑰匙的連續的兩個顧客i和j,建一條邊i->j。現在解釋爲何可以這樣建邊:比如說i擁有豬圈1,2,3的鑰匙,j擁有豬圈1的鑰匙,這樣i,j同時擁有3號豬圈的鑰匙,按理說j只能打開1號豬圈,但i顧客購買豬後,Mirko是可以隨意分配1,2,3中豬的數量的,所以j顧客實質上是可以得到1,2,3中的豬的。
    因爲豬圈有m個,所以我們可以加一個源點s,分別與n個顧客建邊,鑑於上面的建邊方式,s應與每個豬圈的第一個顧客建邊,邊容量爲豬圈中豬的數量,若某個顧客同時爲多個豬圈的第一個顧客,則數量相加。
    每個顧客購買豬的數量是有上限的,所以我們應該引入一個匯點t,每個顧客與t建一條邊,邊容量爲每個顧客需要購買的豬的數量。
#include <iostream>
#include<cstdio>

using namespace std;
const int MAXN=105;
const int INF=(1<<29);
int flow[MAXN][MAXN];//容量限制
int dalta[MAXN];//改變量
int pre[MAXN];
int flag[MAXN];//標號
int m,n;

int EK()
{
    int i,maxflow=0;
    int queue[MAXN],front,rear;
    while(1)
    {
        front=rear=0;
        for(i=1;i<=n+1;i++)
            flag[i]=0;
        flag[0]=1;
        pre[0]=0;
        dalta[0]=INF;
        queue[rear++]=0;
        while(front!=rear&&!flag[n+1])
        {
            int v=queue[front++];
            for(i=1;i<=n+1;i++)
            {
                if(flag[i])
                    continue;
                if(flow[v][i])
                {
                    dalta[i]=min(dalta[v],flow[v][i]);
                    flag[i]=1;
                    pre[i]=v;
                    queue[rear++]=i;
                }
            }
        }
        if(!flag[n+1])
            break;
        maxflow+=dalta[n+1];
        i=n+1;
        while(i!=0)
        {
            flow[pre[i]][i]-=dalta[n+1];
            flow[i][pre[i]]+=dalta[n+1];
            i=pre[i];
        }
    }
    return maxflow;
}

int main()
{
    int i,j;
    int pigs[1005];//每個豬圈中的豬的數量
    int before[1005];//每個豬圈的前一個顧客
    while(~scanf("%d%d",&m,&n))
    {
        for(i=0;i<=n+1;i++)
            for(j=0;j<=n+1;j++)
                flow[i][j]=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d",pigs+i);
            before[i]=-1;
        }
        for(i=1;i<=n;i++)
        {
            int num;
            scanf("%d",&num);
            while(num--)
            {
                scanf("%d",&j);
                if(before[j]==-1)
                {
                    before[j]=i;
                    flow[0][i]+=pigs[j];
                }
                else
                {
                    flow[before[j]][i]=INF;
                    before[j]=i;
                }
            }
            scanf("%d",&j);
            flow[i][n+1]=j;
        }
        printf("%d\n",EK());
    }
    return 0;
}

發佈了117 篇原創文章 · 獲贊 45 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章