poj 3281 Dining

题目链接:poj 3281

题意:
  有N头牛F种食物可以制作,D种饮料可以制作
  然后每行代表一头牛的喜好,开头两个数fi,di表示这头牛喜欢fi种食物,di种饮料,接下来fi个数表示喜欢的食物编号,di个数表示喜欢的饮料的编号
  现在主人使用最优决策制作出F种食物和D种饮料,问怎么喂才能使尽可能多的牛喂饱(喂饱=一份食物一份饮料,且一头牛最多消耗一份食物和一份饮料)
 输出最多喂饱的牛数。

题解:上个图就了解了,图文出处https://blog.csdn.net/ly59782/article/details/52848317


 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

#define INF 0x3f3f3f3f

const int maxn=500;

int N,F,D;
int c[maxn][maxn],dep[maxn];

int bfs(int s,int t)
{
    queue<int > q;
    while(!q.empty()) q.pop();

    memset(dep,-1,sizeof(dep));

    dep[s]=0;
    q.push(s);

    while(!q.empty())
    {
        int u=q.front();
        q.pop();

        for(int v=1;v<=t;v++)
        {
            if(c[u][v]>0&&dep[v]==-1){
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return dep[t]!=-1;
}

int dfs(int u,int mi,int t)
{
    if(u==t) return mi;
    int tmp;

    for(int v=1;v<=t;v++)
    {
        if(c[u][v]>0&&dep[v]==dep[u]+1&&(tmp=dfs(v,min(mi,c[u][v]),t))){

            c[u][v]-=tmp;
            c[v][u]+=tmp;
            return tmp;
        }
    }
    return 0;
}

int dinic(int start,int ends)
{
    int ans=0,tmp;

    while(bfs(start,ends))
    {
        while(1){
            tmp=dfs(start,INF,ends);
            if(tmp==0) break;
            ans+=tmp;
        }
    }

    return ans;
}
int main()
{

    while(~scanf("%d%d%d",&N,&F,&D))
    {
        memset(c,0,sizeof(c));

       int start=1,ends=1+F+2*N+D+1;

        for(int i=2;i<=F+1;i++) ///建立源点到食物的边
            c[1][i]=1;

        for(int i=1+F+1;i<=1+F+N;i++) ///建立牛与牛之间的边
            c[i][i+N]=1;

        for(int i=1+F+2*N+1;i<=1+F+2*N+D;i++) ///建立饮料到终点的边
            c[i][ends]=1;


        for(int i=1;i<=N;i++)
        {
            int food,drink;
            scanf("%d%d",&food,&drink);

            int item;
            while(food--)
            {
                scanf("%d",&item);

                c[item+1][1+F+i]=1; ///建立食物与牛之间的边
            }
            while(drink--)
            {
                scanf("%d",&item);

                c[1+F+N+i][1+F+2*N+item]=1; ///建立牛与饮料之间的边
            }
        }

        printf("%d\n",dinic(start,ends));
    }

    return 0;
}




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值