• poj 1149 PIGS 最大流


    PIGS
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 12924   Accepted: 5721

    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

    解题思路: 

      本题关键是如何构造一个容量网络,

      1. 将顾客看作除源点和汇点外的节点,并且另设两个节点:源点和汇点。

      2.源点和每个猪圈的第1个顾客连边,边的权是开始时猪圈中猪的数量。

      3.若源点和某个节点之间有重边,则将权合并(因此源点流出的流量就是所有的猪圈能提供猪的数目,优化成只有100个顶点,这个是非常好的)

      4.顾客j紧跟着顾客i之后打开某个猪圈,则边<i,j>的权为无穷大;这是因为,如果顾客j紧跟在顾客i之后打开某个猪圈,那么迈克就有可能根据

    顾客j的需求将其他猪圈中的猪调整到该猪圈,这样顾客j就能买到尽可能多的猪.

      5.每个顾客和汇点之间连边,边的权是顾客希望购买猪的数目(因此汇点的流入量就是每个股哭所购买的猪的数目)

    实现代码: 

      增广路算法,预流推进 皆可(因为顶点数目最多为102)

    参考代码: 

      SAP:shortest augment path 

      

    View Code
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MIN(a,b) (a)<(b)?(a):(b)
    const int M = 110;
    const int inf = 0x3fffffff;
    int n, m, A[1010], pre[1010];
    int remain[M][M], h[M], vh[M], S, T, N;
    
    void input()
    {
        S = 0; T = n+1; N = n+2;
        memset( pre, 0, sizeof(pre) );
        memset( remain, 0, sizeof(remain));
    
        for(int i = 1; i <= m; i++)
            scanf("%d", &A[i]);
        int a, k, b;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a);
            for(int j = 1; j <= a; j++)
            {
                scanf("%d", &k );
                if( pre[k] == 0 ){ //源点与第一个打开某猪圈的顾客连边
                    remain[S][i] = remain[S][i] ? (remain[S][i]+A[k]) : A[k];    
                    pre[k] = i;    
                }
                else{
                    int u = pre[k]; //相邻两个打开某猪圈连边
                    remain[u][i] = inf;
                    pre[k] = i;    
                }    
            }
            scanf("%d", &b); //每个顾客与汇点连边
            remain[i][T] = b;
        }
    }
    int DFS( int u, int flow ) 
    {
        if( u == T ) return flow;//找到增广路
        int tmp = h[u]+1, sum = flow; //更新当前点层数
        for(int v = 0; v < N; v++)
        {
            if( remain[u][v] && h[u] == h[v]+1 ) //允许弧,且一层差别
            {
                int p = DFS( v, MIN( sum, remain[u][v]) );
                remain[u][v] -= p; remain[v][u] += p; sum -= p; //更新残留网络
                if( sum == 0 || h[S] == N ) return flow-sum;    
            }
        }
        for(int v = 0; v < N; v++)
            if( remain[u][v] )    
                tmp = MIN( tmp, h[v] );
        if( !( --vh[ h[u] ] ) ) h[S] = N; //间隙优化,当出现断层即可判定无增广路
        else    ++vh[ h[u] = tmp+1 ]; 
        return flow-sum;
    }
    void sap()
    {
        int maxflow = 0;
        memset( h, 0, sizeof(h));
        memset( vh, 0, sizeof(vh));
        vh[S] = N; //0层节点数量为N
        while( h[S] < N )    maxflow += DFS( S, inf );
        printf("%d\n", maxflow );
    }
    int main()
    {
        while( scanf("%d%d", &m, &n) != EOF)
        {
            input();
            sap();
        }
        return 0;
    }
  • 相关阅读:
    Hibernate核心接口和类
    Struts 2基础知识
    博客开篇
    程序员的幽默笑话(深意爆笑)
    追MM的各种算法
    全局css(慕课)
    全局css
    目录的分层
    class 设置多个css属性
    Python爬虫学习:四、headers和data的获取
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2811839.html
Copyright © 2020-2023  润新知