zoukankan      html  css  js  c++  java
  • 网络流(最大流):POJ 1149 PIGS

    PIGS

    Time Limit: 1000ms
    Memory Limit: 10000KB
    This problem will be judged on PKU.
    64-bit integer(整数) IO format: %lld      Java class name: Main
     
    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 arives, 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
      
      建模题,这里需要注意对空间的优化。
      题意:迈克有个养猪场,养猪场里有M个猪圈,每个猪圈都上了锁。迈克没有钥匙,而要买猪的顾客一个接一个来到养猪场,每个顾客有一些猪圈的钥匙,要买一定数量的猪。当每个顾客来时,将有钥匙的猪圈全部打开,从中挑出一些买走,然后迈克可以重新分配这些猪圈里面的猪。当顾客离开后,门又被锁上。问迈克最多可以卖多少猪。
      建模:先从源点给每个猪圈连一条边,容量是猪圈中猪的头数。这时再添加顾客,对于每一个顾客,查找他要开的每一个猪圈,如果他要开猪圈A,那么现在分情况讨论:
      <1>若以前(先后顺序,时间上的)没有顾客开过A猪圈,那么就连一条A到这个顾客的边,容量为INF,同时标记这个人为这个猪圈的“开启者”
      <2>若有,则将A的“开启者”连到这个人,容量为INF
      最后每个顾客连边到汇点,容量为各自的需求,接着跑一遍最大流就可以啦,这里我用了ISAP算法
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue>
      5 
      6 using namespace std;
      7 const int INF=2147483647;
      8 const int maxn=1010,maxm=4010;
      9 int cnt,fir[maxn],nxt[maxm],cap[maxm],to[maxm],dis[maxn],gap[maxn],path[maxn],used[maxn];
     10 
     11 void addedge(int a,int b,int c)
     12 {
     13     nxt[++cnt]=fir[a];
     14     to[cnt]=b;
     15     cap[cnt]=c;
     16     fir[a]=cnt;
     17 }
     18 
     19 bool BFS(int S,int T)
     20 {
     21     memset(dis,0,sizeof(dis));
     22     dis[T]=1;
     23     queue<int>q;q.push(T);
     24     while(!q.empty())
     25     {
     26         int node=q.front();q.pop();
     27         for(int i=fir[node];i;i=nxt[i])
     28         {
     29             if(dis[to[i]])continue;
     30             dis[to[i]]=dis[node]+1;
     31             q.push(to[i]);
     32         }
     33     }
     34     return dis[S];
     35 }
     36 int fron[maxn];
     37 int ISAP(int S,int T)
     38 {
     39     if(!BFS(S,T))
     40         return 0;
     41     for(int i=1;i<=T;i++)++gap[dis[i]];
     42     int p=S,ret=0;
     43     memcpy(fron,fir,sizeof(fir));
     44     while(dis[S]<=T)
     45     {
     46         if(p==T){
     47             int f=INF;
     48             while(p!=S){
     49                 f=min(f,cap[path[p]]);
     50                 p=to[path[p]^1];
     51             }
     52             p=T;ret+=f;
     53             while(p!=S){
     54                 cap[path[p]]-=f;
     55                 cap[path[p]^1]+=f;
     56                 p=to[path[p]^1];
     57             }
     58         }
     59         int &ii=fron[p];
     60         for(;ii;ii=nxt[ii]){
     61             if(!cap[ii]||dis[to[ii]]+1!=dis[p])
     62                 continue;
     63             else 
     64                 break;
     65         }        
     66         if(ii){
     67             p=to[ii];
     68             path[p]=ii;
     69         }
     70         else{
     71             if(--gap[dis[p]]==0)break;
     72             int minn=T+1;
     73             for(int i=fir[p];i;i=nxt[i])
     74                 if(cap[i])
     75                     minn=min(minn,dis[to[i]]);
     76             gap[dis[p]=minn+1]++;
     77             fron[p]=fir[p];
     78             if(p!=S)
     79                 p=to[path[p]^1];        
     80         }
     81     }
     82     return ret;
     83 }
     84 
     85 void Init()
     86 {
     87     memset(fir,0,sizeof(fir));
     88     memset(used,0,sizeof(used)); 
     89     cnt=1;
     90 }
     91 int main()
     92 {
     93     int n,m,num,k,need;
     94     while(~scanf("%d%d",&m,&n))
     95     {
     96         Init();
     97         for(int i=1;i<=m;i++){
     98             scanf("%d",&num);
     99             addedge(0,i,num);
    100             addedge(i,0,0);
    101         }
    102         for(int i=m+1;i<=m+n;i++){
    103             scanf("%d",&k);
    104             while(k--){
    105                 scanf("%d",&num);
    106                 if(used[num]){
    107                     addedge(used[num],i,INF);
    108                     addedge(i,used[num],0);
    109                 }
    110                 else{
    111                     used[num]=i;
    112                     addedge(num,i,INF);
    113                     addedge(i,num,0);
    114                 }
    115                 
    116             }
    117             scanf("%d",&need);
    118             addedge(i,n+m+1,need);
    119             addedge(n+m+1,i,0);
    120         }
    121         printf("%d
    ",ISAP(0,n+m+1));
    122     }
    123     return 0;
    124 }
    尽最大的努力,做最好的自己!
  • 相关阅读:
    HTTPS安全超文本传输协议
    前端性能监控工具
    跨域:跨域及解决方法
    源码安装nginx
    浏览器工作原理(四):浏览器事件解读
    浏览器工作原理(三):js运行机制及Event Loop
    前端性能优化:gzip压缩文件传输数据
    Vue源码学习(零):内部原理解析
    netsh命令操作ipsec
    netsh命令操作防火墙
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5222626.html
Copyright © 2011-2022 走看看