zoukankan      html  css  js  c++  java
  • 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.

    题目大意:有n个人m个猪圈,每个猪圈里有一些猪,这n个人要买猪,每一个人会打开数个猪圈,买一些猪,然后这些猪圈的猪可以移动到另一些猪圈,问最多能卖多少猪。

    思路:最大流。最朴素的想法是每个人建m个猪圈,不过这样搞点太多了。可以看到,若当两个猪圈被同时打开过,那么这此时两个猪圈就可以看成一个猪圈了。于是,对每一个猪圈,从源点到第一个打开它的人连一条边,容量为猪数,然后这个人再往下一个打开这个猪圈的人连一条边,容量为无穷大(其实这样两个人之间可能会有多条无穷大的边,不过我懒得搞,随便啦AC就好)。然后再从每个人连一条边到汇点,容量为这个人要买的猪的数量。最大流为答案。

    PS:之前读入n、m的顺序搞错了WA了一次。n和m一样的样例太可恶了>_<

    代码(16MS):

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 
      8 const int MAXN = 110;
      9 const int MAXE = MAXN * MAXN;
     10 const int INF = 0x7fffffff;
     11 
     12 struct SAP {
     13     int head[MAXN], gap[MAXN], pre[MAXN], dis[MAXN], cur[MAXN];
     14     int next[MAXE], to[MAXE], flow[MAXE];
     15     int ecnt, n, st, ed;
     16 
     17     void init() {
     18         memset(head, 0, sizeof(head));
     19         ecnt = 2;
     20     }
     21 
     22     void add_edge(int u, int v, int c) {
     23         to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
     24         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
     25     }
     26 
     27     void bfs() {
     28         queue<int> que; que.push(ed);
     29         memset(dis, 0x3f, sizeof(dis));
     30         dis[ed] = 0;
     31         while(!que.empty()) {
     32             int u = que.front(); que.pop();
     33             ++gap[dis[u]];
     34             for(int p = head[u]; p; p = next[p]) {
     35                 int &v = to[p];
     36                 if(flow[p ^ 1] && dis[v] > n) {
     37                     dis[v] = dis[u] + 1;
     38                     que.push(v);
     39                 }
     40             }
     41         }
     42     }
     43 
     44     int Max_flow(int ss, int tt, int nn) {
     45         st = ss, ed = tt, n = nn;
     46         int ans = 0, minFlow = INF, u;
     47         for(int i = 0; i <= n; ++i) {
     48             cur[i] = head[i];
     49             gap[i] = 0;
     50         }
     51         bfs();
     52         u = pre[st] = st;
     53         while(dis[st] < n) {
     54             bool flag = false;
     55             for(int &p = cur[u]; p; p = next[p]) {
     56                 int &v = to[p];
     57                 if(flow[p] && dis[u] == dis[v] + 1) {
     58                     flag = true;
     59                     minFlow = min(minFlow, flow[p]);
     60                     pre[v] = u;
     61                     u = v;
     62                     if(u == ed) {
     63                         ans += minFlow;
     64                         while(u != st) {
     65                             u = pre[u];
     66                             flow[cur[u]] -= minFlow;
     67                             flow[cur[u] ^ 1] += minFlow;
     68                         }
     69                         minFlow = INF;
     70                     }
     71                     break;
     72                 }
     73             }
     74             if(flag) continue;
     75             int minDis = n - 1;
     76             for(int p = head[u]; p; p = next[p]) {
     77                 int &v = to[p];
     78                 if(flow[p] && dis[v] < minDis) {
     79                     minDis = dis[v];
     80                     cur[u] = p;
     81                 }
     82             }
     83             if(--gap[dis[u]] == 0) break;
     84             ++gap[dis[u] = minDis + 1];
     85             u = pre[u];
     86         }
     87         return ans;
     88     }
     89 } G;
     90 
     91 int n, m;
     92 int last[1010];
     93 int a[1010], b[110];
     94 
     95 int main() {
     96     scanf("%d%d", &m, &n);
     97     G.init();
     98     int ss = n + 1, tt = n + 2;
     99     for(int i = 1; i <= m; ++i) scanf("%d", &a[i]);
    100     for(int i = 1; i <= n; ++i) {
    101         int x, b;
    102         scanf("%d", &b);
    103         for(int j = 1; j <= b; ++j) {
    104             scanf("%d", &x);
    105             if(last[x] == 0) G.add_edge(ss, i, a[x]);
    106             else G.add_edge(last[x], i, INF);
    107             last[x] = i;
    108         }
    109         scanf("%d", &x); G.add_edge(i, tt, x);
    110     }
    111     printf("%d
    ", G.Max_flow(ss, tt, tt));
    112 }
    View Code
  • 相关阅读:
    Batch Normalization
    常用shell命令
    把chord下dbm_noauth做成静态库,提供接口
    vim中多标签和多窗口的使用
    recv返回值
    在XP下从硬盘安装windows 7的方法
    Linux文件系统中的链接
    统计出现次数排名
    linux编程环境
    windows命令行修改连接的DNS
  • 原文地址:https://www.cnblogs.com/oyking/p/3300918.html
Copyright © 2011-2022 走看看