首页 > 代码库 > poj 1149 PIGS(网络流dinic)

poj 1149 PIGS(网络流dinic)

PIGS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 16054 Accepted: 7185

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

构图的时候把掌管有同一个猪圈的两个人由先到的向后到的引一条无限流量的边!


#include"stdio.h"
#include"string.h"
#include"math.h"
#include"queue"
#include"algorithm"
using namespace std;
#define N 1500
#define min(a,b) (a<b?a:b)
const int inf=0x7fffffff;
int c[N][N],head[N],cnt;
int dis[N],q[N];
struct node
{
    int u,v,w,next;
}map[N*100];
void add(int u,int v,int w)
{
    map[cnt].u=u;
    map[cnt].v=v;
    map[cnt].w=w;
    map[cnt].next=head[u];
    head[u]=cnt++;
    map[cnt].u=v;
    map[cnt].v=u;
    map[cnt].w=0;
    map[cnt].next=head[v];
    head[v]=cnt++;
}
int bfs(int n)
{
    int s=0,t1,t2,x,v,i;
    memset(dis,0,sizeof(dis));
    t1=t2=0;
    q[t1++]=s;
    dis[s]=1;
    while(t2<t1)
    {
        x=q[t2++];
        for(i=head[x];i!=-1;i=map[i].next)
        {
            v=map[i].v;
            if(map[i].w&&!dis[v])
            {
                dis[v]=dis[x]+1;
                if(v==n)
                    return 1;
                q[t1++]=v;
            }
        }
    }
    return 0;
}
int dfs(int s,int n,int lim)
{
    int t=n,i,v,tmp,cost=0;
    if(s==t)
        return lim;
    for(i=head[s];i!=-1;i=map[i].next)
    {
        v=map[i].v;
        if(map[i].w&&dis[v]==dis[s]+1)
        {
            tmp=dfs(v,n,min(lim-cost,map[i].w));
            if(tmp>0)
            {
                map[i].w-=tmp;
                map[i^1].w+=tmp;
                cost+=tmp;
                if(cost==lim)
                    break;
            }
            else
                dis[v]=-1;
        }
    }
    return cost;
}
int dinic(int n)
{
    int ans=0,s=0;
    while(bfs(n))
        ans+=dfs(s,n,inf);
    return ans;
}
int main()
{
    int b,q[N],i,j,k,l,n,m;
    int a[N];
    while(scanf("%d%d",&m,&n)!=-1)
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d",&a[i]);
            add(0,i,a[i]);
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d",&q[i]);  //客户拿的钥匙数目
            for(j=1;j<=q[i];j++)   //猪舍
            {
                scanf("%d",&k);  //能打开的猪舍
                c[i][j]=k;
                add(k,m+i,a[k]);
            }
            scanf("%d",&b);
            add(m+i,m+n+1,b);
            for(j=1;j<i;j++) //寻找该客户之前的客户是否能打开同一个猪舍
            {
                int flag=0;
                for(k=1;k<=q[j];k++)  //某个客户能打开的猪舍
                {
                    for(l=1;l<=q[i];l++)//第I个客户能打开的猪舍
                    {
                        if(c[j][k]==c[i][l])
                        {
                            add(j+m,i+m,inf);  //建一条无限流量的边
                            flag=1;
                            break;
                        }
                    }
                    if(flag)
                        break;
                }
            }
        }
        printf("%d\n",dinic(n+m+1));
    }
    return 0;
}