PIGS (poj 1149 最大流)


Language:
Default

PIGS

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 17332   Accepted: 7862

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

Croatia OI 2002 Final Exam - First day

题意:m个猪圈n个顾客,告诉每个猪圈里猪的数量和顾客的需求量以及告诉顾客会到哪个猪圈买猪,问最多能卖出多少猪。

思路:本题的关键在于如何构造一个容量网络。

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

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

(3)若源点和某个节点之间有重边,则将权合并(因此源点流出的流量就是所有的猪圈能提供的猪的数量)

(4)顾客j紧跟在顾客i之后打开某个猪圈,则<i,j>的权是无穷大;这是因为,如果顾客j紧跟在i之后打开某个猪圈,那么迈克就有可能根据顾客j的需求将其他猪圈的猪调整到该猪圈,这样顾客j就能买到尽可能多的猪。

(5)每个顾客和汇点之间连边,变的权是顾客的购猪数量。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define MAXM 1000000
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

int mp[111][111];//容量
int flow[111][111];//流量
int house[1005],last[1111];
int n,m,s,t;

void MaxFlow()
{
    int i,j,v;
    int pre[111];
    int alpha[111];//可改进量
    queue<int>Q;
    mem(flow,0);
    alpha[s]=INF;
    while (1)
    {
        FRE(i,0,110)
        pre[i]=-2;
        pre[s]=-1;
        Q.push(0);
        while (!Q.empty())
        {
            v=Q.front(); Q.pop();
            for (i=0;i<t+1;i++)
            {
                int p;
                if (pre[i]==-2&&(p=mp[v][i]-flow[v][i])!=0)
                {
                    pre[i]=v;
                    Q.push(i);
                    alpha[i]=min(alpha[v],p);
                }
            }
        }
        if (pre[t]==-2) break;
        for (i=pre[t],j=t;i!=-1;j=i,i=pre[i])
        {
            flow[i][j]+=alpha[t];
            flow[j][i]-=alpha[t];
        }
    }
    int ans=0;
    FRL(i,0,n+1)
    ans+=flow[i][t];
    printf("%d\n",ans);
    return ;
}

int main()
{
    int i,j;
    while (~sff(m,n))
    {
        mem(last,0);
        mem(mp,0);
        FRE(i,1,m)
        sf(house[i]);
        int num=0,x;
        s=0,t=n+1;
        FRE(i,1,n)
        {
            sf(num);
            while (num--)
            {
                sf(x);
                if (last[x]==0)
                    mp[s][i]+=house[x];
                else
                    mp[last[x]][i]=INF;
                last[x]=i;
            }
            sf(mp[i][t]);
        }
        MaxFlow();
    }
    return 0;
}

另附非递归dinic:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define MAXM 1000000
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

struct Edge{
    int to,next,cap,flow;
}edge[MAXM];

int tol,n,m;
int head[MAXN];
int house[1005];
int vis[1005];
int mp[111][111];

void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;
    edge[tol].cap=w;
    edge[tol].flow=0;
    edge[tol].next=head[u];
    head[u]=tol++;

    edge[tol].to=u;
    edge[tol].cap=rw;//双向边时改成w
    edge[tol].flow=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}

int Q[MAXN];
int dep[MAXN],cur[MAXN],sta[MAXN];

bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while (front<tail)
    {
        int u=Q[front++];
        for (int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if (edge[i].cap>edge[i].flow && dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                if (v==t) return true;
                Q[tail++]=v;
            }
        }
    }
    return false;
}

int dinic(int s,int t,int n)
{
    int maxflow=0;
    while (bfs(s,t,n))
    {
        for (int i=0;i<n;i++) cur[i]=head[i];
        int u=s,tail=0;
        while (cur[s]!=-1)
        {
            if (u==t)
            {
                int tp=INF;
                for (int i=tail-1;i>=0;i--)
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                maxflow+=tp;
                for (int i=tail-1;i>=0;i--)
                {
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if (edge[sta[i]].cap-edge[sta[i]].flow==0)
                        tail=i;
                }
                u=edge[sta[tail]^1].to;
            }
            else if (cur[u]!=-1 && edge[cur[u]].cap > edge[cur[u]].flow &&dep[u]+1==dep[edge[cur[u]].to])
            {
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }
            else
            {
                while (u!=s && cur[u]==-1)
                    u=edge[sta[--tail]^1].to;
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}

int main()
{
    int i,j;
    while (~sff(m,n))
    {
        init();
        mem(vis,0);
        mem(mp,0);
        FRE(i,1,m)
        sf(house[i]);
        int num,s=0,t=n+1,x;
        FRE(i,1,n)
        {
            sf(num);
            while (num--)
            {
                sf(x);
                if (!vis[x])
                    mp[s][i]+=house[x];
                else
                    mp[vis[x]][i]=INF;
                vis[x]=i;
            }
            sf(mp[i][t]);
        }
        FRE(i,0,n+1)
        FRE(j,i,n+1)
        if (mp[i][j]!=0)
            addedge(i,j,mp[i][j]);
        int ans=dinic(s,t,n+2);
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-01 04:57:28

PIGS (poj 1149 最大流)的相关文章

PIGS POJ - 1149(水最大流)

题意: 有M个猪圈,每个猪圈里初始时有若干头猪.一开始所有猪圈都是关闭的.依次来了N个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪.每个顾客分别都有他能够买的数量的上限.每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上.问总共最多能卖出多少头猪.(1 <= N <= 100, 1 <= M <= 1000) 解析: 因为是依次 所以对于当前第i个顾客 所对应的猪圈 向前 i - 1 个顾客种有对应这个猪圈的顾客的其它猪圈 就

POJ 1149 最大流+构图

点击打开链接 题意:有m个猪圈,n个商人,每个商人会买固定猪圈的猪,在每个商人买完猪后,我可以调整开着门的猪圈的住的个数,可以从其他开着门的猪圈调过来,问n个商人最多能买走多少猪 思路:o(︶︿︶)o 唉,做最大流的构图题,做一个就像之前从没做过最大流似的,膜拜神犇们~~~~,看了后确实简单,如果这个猪圈是第一次打开,那么这个猪圈就可以将所有都指向这个商人,就建一条到这个商人的一条这个猪圈的猪的数量,如果不是第一次,那么就找到上一次打开这个猪圈的人,那个人连一条inf的边到目前这个商人,想想确实

POJ 1149 PIGS 最大流

第一次做网络流,看着教材里面的题解做的= = 用的是Ford,应该是最好理解的把,就是不断的找有没有从源点到汇点的增广路然后更新. 建图真是难啊,而且感觉细节要注意的地方比较多,一开始没有考虑反向弧,WA了两发,sad... #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <strin

POJ 1149 PIGS(Dinic最大流)

PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20738   Accepted: 9481 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 t

POJ 1149 PIGS(最大流+建图)

题目链接:http://poj.org/problem?id=1149 题意:M个猪圈,N个顾客,每个顾客有一些的猪圈的钥匙,只能购买能打开的猪圈里的猪,而且要买一定数量的猪,每个猪圈有已知数量的猪, 但是猪圈可以重新打开,将猪的个数,重新分配,但是只能将猪往当前打开状态的猪圈里赶,以达到卖出的猪的数量最多. 思路:还是4部分,源点->猪圈->猪圈->汇点 Accepted 976K 63MS C++ 能用EK水的,当然用EK水 #include <iostream> #in

POJ 1149 PIGS(最大流)

POJ 1149 PIGS 题目链接 题意:有n个猪圈,m个顾客,猪圈中一开始有一些猪,顾客轮流来(注意是有先后顺序的),然后每个顾客会开启一些猪圈,在开启的猪圈中最多买b只猪,之后可以任意把剩下的猪分配到开着的猪圈中,问最多能卖出几只猪 思路:这题的关键在于建模,由于顾客有先后顺序,假如后来的顾客会开启x门,前面一个顾客也会开启x门,那么前面顾客相当与可以分配给后面顾客, 所以建模的方式为,源点和每个猪圈连,容量为猪圈猪数,每个猪圈和第一个开的顾客连,如果后面有顾客会开这个猪圈,则和之前的顾客

POJ 1149 PIGS 迈克卖猪问题 网络流构图+三种AC方法

题目链接:POJ 1149 PIGS PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16533   Accepted: 7403 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 key

poj 1149 PIGS(网络流dinic)

PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16054   Accepted: 7185 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 t

POJ 1149 网络流 合并建图

这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独建点,猪圈无非就是向顾客输送流量 以及向同时开着的猪圈输送流量,这一步可以直接缩为,当某个猪圈被第一次打开,它里面的流量就全部输送给那个顾客那个点,而且可以叠加,因为每一次猪圈是可以互通的,而且猪圈本身是没有容量限制,如果有限制,那就还得再考虑. 此外,每次对猪圈的接下来的访问者都进行建边.用来输送