zoukankan      html  css  js  c++  java
  • POJ3281:Dining(dinic+拆点)

    题目链接:http://poj.org/problem?id=3281

    PS:刷够网络流了,先这样吧,之后再刷,慢慢补。

    题意:有F种食物,D种饮料,N头奶牛,只能吃某种食物和饮料(而且只能吃特定的一份),一种食物被一头牛吃了之后,其余牛就不能吃了 第一行有N,F,D三个整数:接着2-N+1行代表第i头牛,前面两个整数是Fi与Di(食物与饮料的种类数量),接着是食物的种类与饮料的种类 要求输出最多分配能够满足的牛的数量.

    思路:这是一种神奇的建图方式-拆点。让我想打死都想不出来。sad

    建图,有2*n+f+d+2个顶点,0表示源点,2*n+f+d+1表示汇点。 由源点指向食物,再由食物指向牛,牛再指向对应的饮料,饮料再指向汇点 当然要使每一头牛都对应每一份食物与饮料,所以应该牛i指向牛i再指向饮料,这样就可以避免一头牛只占用多份食物与饮料了 全部是有向的边,而且权值全部为1 我在这里是1到f为食物点,f+1到f+2*n为牛点,f+2*n+1到f+2*n+d为饮料点

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define N 1100
    #define inf 0x3f3f3f3f
    typedef int ll;
    using namespace std;
    ll n,f,d,tt,dis[N],head[N];
    struct node
    {
        ll x,y,w,next;
    } eg[N*N];
    void init()
    {
        tt=0;
        memset(head,-1,sizeof(head));
    }
    void add(int xx,int yy)
    {
        eg[tt].x=xx;
        eg[tt].y=yy;
        eg[tt].w=1;
        eg[tt].next=head[xx];
        head[xx]=tt++;
        eg[tt].x=yy;
        eg[tt].y=xx;
        eg[tt].w=0;
        eg[tt].next=head[yy];
        head[yy]=tt++;
    }
    bool bfs(int s,int e)
    {
        memset(dis,-1,sizeof(dis));
        dis[s]=0;
        queue<int>q;
        q.push(s);
        while(!q.empty())
        {
            int fa=q.front();
            q.pop();
            for(int i=head[fa]; i!=-1; i=eg[i].next)
            {
                int v=eg[i].y;
                if(dis[v]==-1&&eg[i].w)
                {
                    dis[v]=dis[fa]+1;
                    q.push(v);
                }
            }
        }
        if(dis[e]>0)
            return true;
        return false;
    }
    int dinic(int s,int maxt)
    {
        if(s==2*n+f+d+1) return maxt;
        int a,sum=maxt;
        for(int i=head[s]; i!=-1; i=eg[i].next)
        {
            int v=eg[i].y;
            if(dis[v]==dis[s]+1&&eg[i].w>0)
            {
                a=dinic(v,min(sum,eg[i].w));
                eg[i].w-=a;
                eg[i+1].w+=a;
                sum-=a;
            }
        }
        return maxt-sum;
    }
    int main()
    {
        ll xx,yy,s1,s2;
        scanf("%d%d%d",&n,&f,&d);
    
            init();
            for(int j=1;j<=f;j++)
            {
                add(0,j);
            }
            for(int j=1;j<=d;j++)
            {
                add(f+2*n+j,f+2*n+d+1);
            }
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&s1,&s2);
                for(int j=1;j<=s1;j++)
                {
                    scanf("%d",&xx);
                    add(xx,f+i);
                }
                for(int j=1;j<=s2;j++)
                {
                    scanf("%d",&yy);
                    add(f+n+i,f+2*n+yy);
                }
            }
            for(int i=1;i<=n;i++)
            {
                add(f+i,f+n+i);
            }
            ll ans=0;
            while(bfs(0,2*n+f+d+1))
            {
                ans+=dinic(0,inf);
            }
            printf("%d
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    MERGE引擎 分表后 快速查询所有数据
    MYSQL导入中文数据乱码的四种解决办法
    数据库中为什么不推荐使用外键约束?
    Word转PDF
    YII2 更新数据不成功
    YII2 使用curl请求,返回false
    Yii集成PHPWord
    网站安全DDOS攻击及监测
    nginx日志
    定时任务秒级执行
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4252870.html
Copyright © 2011-2022 走看看