zoukankan      html  css  js  c++  java
  • POJ1149_PIGS(网络流/EK)

    PIGS
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 15721   Accepted: 7021

    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

    解题报告
    昨天開始学网络流,这是第一题网络流建图的题。
    题目意思:
    养猪场M个猪圈。每一个猪圈都上锁,主人又没有钥匙。N个顾客买猪。且每一个顾客有一些猪圈的钥匙(这是什么情况,主人没有钥匙。反而买主有钥匙。sad...)
    一天,要到养猪场买猪的顾客都会提前告诉养猪场主人。包含拥有的钥匙。买几头猪。养猪场主人能够安排销售计划使得卖出去的猪数目最大。
    每当顾客来了。会把他拥有钥匙的猪圈全都打开,养猪场主人挑一些猪买出去,养猪场主人还能够又一次分配被打开猪圈的猪。

    猪圈能够容纳猪的数量不限。

    思路:
    由于一開始猪圈是上锁的。所以把顾客其中转站,另设两节点,源点和汇点。
    源点和每一个猪圈的第一个顾客连边。边的权值是猪圈里的猪的数目。
    顾客j紧跟着顾客i打开某猪圈,则<i,j>的权值是+oo,表示假设顾客j在顾客i之后打开猪圈,主人能够跟据顾客j的需求把其它猪圈的猪赶到该猪圈,这样顾客j就能够买到尽可能多的猪。
    每一个顾客和汇点相连。边权是每一个顾客的需求量。

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #define inf 99999999
    #define M 10100
    #define N 1100
    using namespace std;
    int pigh[M],edge[N][N],p[N],a[N],pre[N],m,n,flow;
    queue<int >Q;
    void ek()
    {
        while(1)
        {
            while(!Q.empty())Q.pop();
            memset(a,0,sizeof(a));
            memset(p,0,sizeof(p));
            a[0]=inf;
            Q.push(0);
            while(!Q.empty())
            {
                int u=Q.front();
                Q.pop();
                for(int v=0;v<=n+1;v++)
                {
                    if(!a[v]&&edge[u][v]>0)
                    {
                        a[v]=min(a[u],edge[u][v]);
                        p[v]=u;
                        Q.push(v);
                    }
                }
                if(a[n+1])break;
            }
            if(!a[n+1])break;
            for(int u=n+1;u!=0;u=p[u])
            {
                edge[p[u]][u]-=a[n+1];
                edge[u][p[u]]+=a[n+1];
            }
            flow+=a[n+1];
        }
    }
    int main()
    {
        int i,j,k,u,b;
        while(~scanf("%d%d",&m,&n))
        {
            flow=0;
            memset(pigh,0,sizeof(pigh));
            memset(edge,0,sizeof(edge));
            memset(pre,0,sizeof(pre));
            for(i=1; i<=m; i++)
                scanf("%d",&pigh[i]);
            for(i=1; i<=n; i++)
            {
                scanf("%d",&k);
                while(k--)
                {
                    scanf("%d",&u);
                    if(!pre[u])
                    {
                        edge[pre[u]][i]+=pigh[u];
                        pre[u]=i;
                    }
                    else
                    {
                        edge[pre[u]][i]=inf;
                        pre[u]=i;
                    }
                }
                scanf("%d",&b);
                edge[i][n+1]+=b;
            }
            ek();
    //        for(i=0;i<=n+1;i++)
    //        {
    //            for(j=0;j<=n+1;j++)
    //            {
    //                cout<<edge[i][j]<<" ";
    //            }
    //            cout<<endl;
    //        }
            printf("%d
    ",flow);
        }
        return 0;
    }
    


查看全文
  • 相关阅读:
    应用 memcached 提升站点性能
    Servlet 工作原理解析
    AJAX的一些基础和AJAX的状态
    回调地狱以及用promise怎么解决回调地狱
    Ajax的封装
    promise的理解和应用
    jsonp跨域
    浅谈事件冒泡和事件捕获
    JS中的兼容问题总结
    JS写的二级导航栏(利用冒泡原理)
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10830460.html
  • Copyright © 2011-2022 走看看