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

Source

Croatia OI 2002 Final Exam - First day

思路

建立一个源点和汇点,把源点向第一个打开一个猪圈的人连一条猪圈容量的边,把每个人向汇点连这个人需要猪数量的边,把不是第一个打开一个猪圈的人向上一个打开这个猪圈的人连一条容量为无限的边(因为可以安排打开猪圈的猪的数量)。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn=100;
const int maxm=40000;
const int inf=0x3f3f3f3f;

struct queue
{
  int q[maxn+10],head,tail;

  inline int empty()
  {
    return head==tail;
  }

  inline int push(int x)
  {
    ++tail;
    q[tail]=x;
    return 0;
  }

  inline int front()
  {
    return q[head+1];
  }

  inline int pop()
  {
    if(empty())
      {
        return -1;
      }
    ++head;
    return 0;
  }

  inline int mem()
  {
    return head=tail=0;
  }
};

int n;

struct graph
{
  int pre[maxm+10],now[maxn+10],son[maxm+10],val[maxm+10],tot,t[maxn+10];
  queue q;

  inline int ins(int a,int b,int c)
  {
    ++tot;
    pre[tot]=now[a];
    now[a]=tot;
    son[tot]=b;
    val[tot]=c;
    ++tot;
    pre[tot]=now[b];
    now[b]=tot;
    son[tot]=a;
    val[tot]=0;
    return 0;
  }

  inline int bfs()
  {
    q.mem();
    memset(t,0,sizeof t);
    q.push(0);
    t[0]=1;
    while(!q.empty())
      {
        int u=q.front(),j=now[u];
        q.pop();
        while(j)
          {
            int v=son[j];
            if(val[j]&&(!t[v]))
              {
                t[v]=t[u]+1;
                q.push(v);
                if(v==n+1)
                  {
                    return 1;
                  }
              }
            j=pre[j];
          }
      }
    return 0;
  }

  inline int dfs(int u,int flow)
  {
    if(u==n+1)
      {
        return flow;
      }
    int j=now[u],res=flow;
    while(j&&res)
      {
        int v=son[j];
        if(val[j]&&(t[v]==t[u]+1))
          {
            int k=dfs(v,std::min(res,val[j]));
            val[j]-=k;
            val[j^1]+=k;
            res-=k;
          }
        j=pre[j];
      }
    return flow-res;
  }

  inline int mem()
  {
    memset(now,0,sizeof now);
    tot=1;
    return 0;
  }
};

int m,cnt[maxm+10],v[maxm+10],pre[maxm+10],ans;
graph g;

int main()
{
  g.mem();
  scanf("%d%d",&m,&n);
  for(register int i=1; i<=m; ++i)
    {
      scanf("%d",&v[i]);
    }
  for(register int i=1; i<=n; ++i)
    {
      memset(cnt,0,sizeof cnt);
      int a,b;
      scanf("%d",&a);
      while(a--)
        {
          scanf("%d",&b);
          if(pre[b])
            {
              cnt[pre[b]]=inf;
            }
          else
            {
              cnt[pre[b]]+=v[b];
            }
          pre[b]=i;
        }
      scanf("%d",&b);
      g.ins(i,n+1,b);
      for(register int j=0; j<=m; ++j)
        {
          if(cnt[j])
            {
              g.ins(j,i,cnt[j]);
            }
        }
    }
  while(g.bfs())
    {
      ans+=g.dfs(0,inf);
    }
  printf("%d\n",ans);
  return 0;
}