zoukankan      html  css  js  c++  java
  • poj 1149 PIGS

    PIGS
    Time Limit: 1000MS   Memory Limit: 10000K
         

    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

    题目大意:
    Mirko 养着一些猪, 猪关在一些猪圈里面, 猪圈是锁着的他自己没有钥匙 (汗)
    只有要来买猪的顾客才有钥匙, 顾客依次来每个顾客会用他的钥匙打开一些猪圈买
    走一些猪, 然后锁上.
    在锁上之前 Mirko 有机会重新分配这几个已打开猪圈的猪, 现在给出一开始每个猪
    圈的猪数, 每个顾客所有的钥匙和要买走的猪数问 Mirko 最多能卖掉几头猪
    以样例输入为例
    有m个猪圈,n个顾客
    接下来一行有m个数,表示每个猪圈开始猪的数量
    接下来n行,
    每行第一个数表示第i个顾客手里的钥匙数p,后面p个数表示是哪个猪圈的钥匙,最后一个数表示他要买的猪的数量
    最大流
    很容易想到的建图方法
     
    上图修改如下:
     
    但是这样会有100000左右个点,TLE
    所以我们要对点进行合并
    合并规则:
    规律 1. 如果几个节点的流量的来源完全相同,则可以把它们合并成一个。
     规律 2. 如果几个节点的流量的去向完全相同,则可以把它们合并成一个。
      规律 3. 如果从点 u 到点 v 有一条容量为 +∞ 的边,并且 u 是 v 的唯一流量来源,或者 v 是 u 的唯一流量去向,则可以把 u 和 v 合并成一个节点。
    所以最终构图方式:
    1、由源点向每个猪圈第一个要访问的顾客连一条边,流量为一开始猪的数量,如果源点向同一个顾客有多条边,就把他们合并为1条边,流量相加。
    2、如果顾客j在顾客i后访问猪圈k,则由i向j连一条流量为inf的边
    3、每个顾客向汇点连一条边,流量为他要买的猪的数量
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define inf 600001
    using namespace std;
    int n,m,qq,tot=1,ans;
    int src,decc;
    int front[112],cap[22001],lev[112],cnt[112],nextt[22001],to[22001];
    queue<int>q;
    int pre[1002],buy[112],kai[112][112],last[1002];
    void add(int u,int v,int w)
    {
        to[++tot]=v;cap[tot]=w;nextt[tot]=front[u];front[u]=tot;
        to[++tot]=u;cap[tot]=0;nextt[tot]=front[v];front[v]=tot;
    }
    bool bfs()
    {
        for(int i=0;i<=m+1;i++) {cnt[i]=front[i];lev[i]=-1;}
        while(!q.empty()) q.pop();
        q.push(src);lev[src]=0;
        while(!q.empty())
        {
            int now=q.front();q.pop();
            for(int i=front[now];i!=0;i=nextt[i])
            {
                int t=to[i];
                if(cap[i]>0&&lev[t]==-1)
                {
                    q.push(t);
                    lev[t]=lev[now]+1;
                    if(t==decc) return true;
                }
            }
        }
        return false;
    }
    int dinic(int now,int flow)
    {
        if(now==decc) return flow;
        int delta,rest=0;
        for(int & i=cnt[now];i!=0;i=nextt[i])
        {
            int t=to[i];
            if(lev[t]==lev[now]+1&&cap[i]>0)
            {
                delta=dinic(t,min(cap[i],flow-rest));
                if(delta)
                {
                    cap[i]-=delta;cap[i^1]+=delta;
                    rest+=delta;if(rest==flow) break;
                }
            }
        }
        if(rest!=flow) lev[now]=-1;
        return rest;
    }
    int main()
    {
       scanf("%d%d",&n,&m);  
       int p,x;
       for(int i=1;i<=n;i++) scanf("%d",&pre[i]);
       for(int i=1;i<=m;i++)
       {
               scanf("%d",&p);
               for(int j=1;j<=p;j++) 
               {
                   scanf("%d",&x);
                   if(!last[x])
                   {
                       kai[0][i]+=pre[x];
                       last[x]=i;
                }
                else kai[last[x]][i]=inf;
            }
            scanf("%d",&buy[i]);
       }
        decc=m+1;
        for(int i=0;i<=m;i++)
         for(int j=0;j<=m;j++)
          if(kai[i][j])     add(i,j,kai[i][j]);
        for(int i=1;i<=m;i++) add(i,decc,buy[i]);
        while(bfs()) 
         ans+=dinic(src,inf);
        printf("%d",ans);
    
    }
  • 相关阅读:
    SQL Server解惑——查询条件IN中能否使用变量
    依赖注入高级玩法——注入接口服务的多个实现类
    最纯净的硬件检测工具箱
    批处理体会hosts文件
    针对m3u8视频的ts文件解密
    HLS协议之m3u8和ts流格式详解
    您的主机不满足在启用Hyper-V或Device/Credential Guard的情况下运行VMwareWorkstation的最低要求
    FFmpeg的安装和使用
    如何下载 blob 地址的视频资源
    Win10系统创建WiFi热点的两种方法
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6498330.html
Copyright © 2011-2022 走看看