POJ 3281 Dining(网络流经典构图)

题目链接

题目大意:农夫John有N头牛,每头牛都有自己喜欢的食物和水的种类,一共有F种食物和D种水,现在让你来进行分配,每种食物或水只能分配给一头牛,并且每头牛只能得到一种食物和一种水,问最多能使几头牛同时享用到自己喜欢的食物和饮料。(1 <= N <= 100, 1 <= F <= 100, 1 <= D <= 100)

分析:这题第一反应很容易往二分图匹配想,但是因为现在有食物和水两种东西,且必须同时满足,那么很明显二分图匹配是不行的,看了网上的题解,不得不佩服这些神犇,这题是用的最大流来做的,设置一个源点和一个终点,将食物和水放在两端,将每头牛拆成两个点放在中间。最大流的正确性依赖于它的每一条s->t流都与一种实际方案一一对应。此题需要用s-t流将一头牛和它喜欢的食物和饮料连接,而食物和饮料之间没有直接关系,自然就想到把牛放在中间,两边是食物和饮料,即s->食物->牛->饮料->t,每条边的权值都为1,故如果形成一条这样的流,就构成一种分配方案。但是还要考虑每头牛是唯一的,故需要考虑牛这个点的权值为1的问题,这时就用到拆点。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<utility>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define Clear(x) memset(x,0,sizeof(x))
#define fup(i,a,b) for(int i=a;i<b;i++)
#define rfup(i,a,b) for(int i=a;i<=b;i++)
#define fdn(i,a,b) for(int i=a;i>b;i--)
#define rfdn(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const double pi=acos(-1.0);
const int maxn = 5e2+7;
const int inf = 0x3f3f3f3f;
int pre[maxn],cap[maxn][maxn],flow[maxn];
int vs,ed;

void CLEAR(queue<int>&q)
{
    queue<int>q1;
    swap(q1,q);
}

int BFS()
{
    queue<int>q;
    CLEAR(q);
    memset(pre,-1,sizeof(pre));
    pre[vs]=0;
    flow[vs]=inf;
    q.push(vs);
    while(!q.empty())
    {
        int index=q.front();
        q.pop();
        rfup(i,0,ed)
        {
            if(i!=vs&&pre[i]==-1&&cap[index][i])
            {
                pre[i]=index;
                flow[i]=min(cap[index][i],flow[index]);
                q.push(i);
            }
        }
    }
    if(pre[ed]==-1)//如果找不到增广路
        return -1;
    return flow[ed];
}

int maxflow()
{
    int sum=0;
    int add,last,now;
    while((add=BFS())!=-1)
    {
        int now=ed;
        while(now!=vs)
        {
            last=pre[now];
            cap[last][now]-=add;
            cap[now][last]+=add;
            now=last;
        }
        sum+=add;
    }
    return sum;
}

int main()
{
    int N,F,D;
    while(scanf("%d%d%d",&N,&F,&D)!=EOF)
    {
        Clear(cap),Clear(flow);
        vs=0;ed=F+2*N+D+1;
        rfup(i,1,F) cap[vs][i]=1;
        rfup(i,F+2*N+1,F+2*N+D) cap[i][ed]=1;
        rfup(i,1,N) cap[F+2*i-1][F+2*i]=1;
        int a,b,u;
        rfup(i,1,N)
        {
            scanf("%d%d",&a,&b);
            while(a--)
            {
                scanf("%d",&u);
                cap[u][F+2*i-1]=1;
            }
            while(b--)
            {
                scanf("%d",&u);
                cap[F+2*i][F+2*N+u]=1;
            }
        }
        printf("%d\n",maxflow());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41311604/article/details/81382666