POJ 1149--PIGS

题意:

  有m个猪圈,n个顾客,这些顾客按顺序购买,每个顾客有若干猪圈的钥匙,可以从其中购买猪,在一个顾客买完之后,可以将这个顾客可以打开的猪圈内的猪重新调整,问最多这些顾客能买走多少猪

 

算法:网路最大流

    用顾客来作为节点,顾客数最多为100,时间和空间都可以达到要求。新增源点s,汇点t,对于每个顾客来说,如果他是第一个打开某猪圈的,则从s向他连一条容量为该猪圈初始值的边,如果与源点的流量已经不是0,则合并,如果不是第一个,则从上一个打开该猪圈的顾客向这个顾客连一条容量为+oo的边,每个顾客向汇点连一条容量为该顾客希望购买的猪的数量的边

    首先按上面的方法构造一个容量网路,再从初始流(零流)出发进行标号,调整。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 300000000
#define MAXM 1000
#define MAXN 100
int s,t;        //源点,汇点
int customer[MAXN+2][MAXN+2];//各节点之间的容量
int flow[MAXN+2][MAXN+2];    //节点之间的流量
int i,j;
void init()
{
    int M,N;
    int num;
    int k;                 //第k个猪圈的钥匙
    int house[MAXM] ;   //储存每个猪圈中猪的个数
    int last[MAXM];  //储存每个猪圈的前一个顾客的钥匙数
    memset(last,0,sizeof(last));
    memset(customer,0,sizeof(customer));
    scanf("%d%d",&M,&N);
    s=0;
    t=N+1;
    for(i=1; i<=M; i++)
        scanf("%d",&house[i]);
    for(i=1; i<=N; i++)
    {
        scanf("%d",&num);
        for(j=0; j<num; j++)
        {
            scanf("%d",&k);
            if(last[k]==0)
                customer[s][i]=customer[s][i]+house[k];
            else
                customer[last[k]][i]=INF;
            last[k]=i;
        }
        scanf("%d",&customer[i][t]);
    }
}
void ford()
{
    int prev[MAXN+2];
    int minflow[MAXN+2];
    int queue[MAXN+2];
    int qs,qe;
    int v;
    int p;
    for(i=0; i<MAXN+2; i++)
    {
        for(j=0; j<MAXN+2; j++)
        {
            flow[i][j]=0;
        }
    }
    minflow[0]=INF;
    while(1)
    {
        for(i=0; i<MAXN+2; i++)
            prev[i]=-2;
        prev[0]=-1;
        qs=0;
        queue[qs]=0;
        qe=1;
        while(qe>qs&&prev[t]==-2)
        {
            v=queue[qs];
            qs++;
            for(i=0; i<t+1; i++)
            {
                if(prev[i]==-2&&(p=customer[v][i]-flow[v][i]))
                {
                    prev[i]=v;
                    queue[qe]=i;
                    qe++;
                    minflow[i]=(minflow[v]<p)?minflow[v]:p;
                }
            }
        }
        if(prev[t]==-2) break;
        for(i=prev[t],j=t;i!=-1;j=i,i=prev[i])
        {
            flow[i][j]=flow[i][j]+minflow[t];
            flow[j][i]=-flow[i][j];
        }
    }
    p=0;
    for(i=0;i<t;i++)
    {
        p=p+flow[i][t];
    }
    printf("%d\n",p);
}
int main()
{
    init();
    ford();
    return 0;
}

 

posted @ 2017-07-31 20:31  枫虹  阅读(106)  评论(0编辑  收藏  举报