POJ 1149 PIGS

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值