POJ 1149 PIGS (最大流)

PIGS
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 19711   Accepted: 9035

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

分析
主要是建图,增加一个源点和汇点,将源点和第一个有这个猪圈钥匙的顾客连起来,边权就是这个猪圈猪的数量,如果源点和某个节点有重边的话,合并就是了
之后的顾客对于已经开了的猪圈,将上一个顾客和他相连,边权是正无穷,可以用一个last数组来记录上一个买这个猪圈的顾客
每个顾客和汇点相连,边权是他想买猪的数量。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
//****************************************************
//最大流模板Edmonds_Karp算法
//初始化:G[][],st,ed
//******************************************************
const int MAXN = 200+10;
const int INF = 0x3fffffff;
int G[MAXN][MAXN];//存边的容量,没有边的初始化为0
int path[MAXN],flow[MAXN],st,ed;
int n;//点的个数,编号0~n,n包括了源点和汇点

queue<int>q;
int bfs()
{
    int i,t;
    while(!q.empty()) q.pop();//清空队列
    memset(path,-1,sizeof(path));//每次搜索前都把路径初始化成-1
    path[st]=0;
    flow[st]=INF;//源点可以有无穷的流流进
    q.push(st);
    while(!q.empty()){
        t=q.front();
        q.pop();
        if(t==ed) break;
        for(i=0;i<=n;i++){
            if(i!=st&&path[i]==-1&&G[t][i]){
                flow[i]=flow[t]<G[t][i]?flow[t]:G[t][i];
                q.push(i);
                path[i]=t;
            }
        }
    }
    if(path[ed]==-1) return -1;//即找不到汇点上去了。找不到增广路径了
    return flow[ed];
}

int Edmonds_Karp()
{
    int max_flow=0;
    int step,now,pre;
    while((step=bfs())!=-1){
        max_flow+=step;
        now=ed;
        while(now!=st){
            pre=path[now];
            G[pre][now]-=step;
            G[now][pre]+=step;
            now=pre;
        }
    }
    return max_flow;
}

int val[1100];
int last[1100];

int main()
{
    int N,M;
    scanf("%d%d",&M,&N);
    st=0,ed=N+1,n=N+1;
    memset(val,0,sizeof(val));
    memset(last,0,sizeof(last));
    for(int i=1;i<=M;i++) scanf("%d",&val[i]);
    for(int i=1;i<=N;i++){
        int A,B,v;
        scanf("%d",&A);
        for(int j=1;j<=A;j++){
            scanf("%d",&v);
            if(last[v]==0){
                G[st][i]+=val[v];
                last[v]=i;
            }
            else{
                G[last[v]][i]=INF;
                last[v]=i;
            }
        }
        scanf("%d",&B);
        G[i][ed]=B;
    }
    printf("%d\n",Edmonds_Karp());

    return 0;
}

 



posted @ 2016-06-25 17:34  季末Despair  阅读(190)  评论(0编辑  收藏  举报