poj 3281(最大流)

 题目大意就是有n头牛,f种食物,d种饮料,每头牛都有其喜欢的食物和饮料,然后每一种食物和每一种饮料只能分配给一头牛,然后如果一头牛得到了它喜欢的食物和饮料的话,该牛就得到满足,问最多可以满足多少头牛。

这题建图非常的巧妙,最大流建图就是把食物和饮料放在两边,一头牛拆成牛左和牛右,每头牛的牛左和牛右的容量为1。每头牛喜欢的食物和该牛的牛左连边,容量为1,每头牛喜欢的饮料和该牛连边,容量为1,然后设一个源点,源点和全部食物连边,容量为1,最后设一个汇点,所以饮料和汇点连边,容量为1.这样图就建好了,跑个网络流最大流即可,我之前用的ek算法的板子在交这题时T了,所以换了个kuangbin的bfs实现的ek算法。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
int mp[505][505],flow[505],path[505];
int n,f,d,maxflow,st,et;

void init()
{
    memset(mp,0,sizeof(mp));

    maxflow=0;
}
bool bfs()
{
    int i,t;
    queue<int>q;
    while(!q.empty()) q.pop();
    memset(path,-1,sizeof(path));
    path[st]=0;
    flow[st]=inf;
    q.push(st);
    while(!q.empty())
    {
        t=q.front();
        q.pop();
        if(t==et) break;
        for(int i=st;i<=et;i++)
        {
            if(i!=st&&path[i]==-1&&mp[t][i])
            {
                flow[i]=min(flow[t],mp[t][i]);
                q.push(i);
                path[i]=t;
            }
        }
    }
    if(path[et]==-1)
        return false;
    return true;
}
void ek()
{
    while(bfs())
    {
        maxflow+=flow[et];
        int now=et,pre;
        while(now!=st)
        {
            pre=path[now];
            mp[pre][now]-=flow[et];
            mp[now][pre]+=flow[et];
            now=pre;
        }
    }

}
int main()
{
    scanf("%d%d%d",&n,&f,&d);
    init();
    st=0;
    et=f+d+2*n+1;
    for(int i=1;i<=f;i++)
        mp[st][i]=1;
    for(int i=f+2*n+1;i<=f+2*n+d;i++)
        mp[i][et]=1;
    for(int i=1;i<=n;i++)
        mp[f+2*i-1][f+2*i]=1;
    int k1,k2;
    int u;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&k1,&k2);
        while(k1--)
        {
            scanf("%d",&u);
            mp[u][f+2*i-1]=1;
        }
        while(k2--)
        {
            scanf("%d",&u);
            mp[f+2*i][f+2*n+u]=1;
        }
    }
    ek();
    printf("%d\n",maxflow);
    return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_40642465/article/details/81347602
今日推荐