zoukankan      html  css  js  c++  java
  • 吃饭【网络流】

    题目大意:

    n头牛,每头牛有自己喜欢的食物和饮料,每种食物或饮料只有一个。求最多能让多少头牛吃到食物并喝到饮料。
    Input

    4 3 3
    2 2 1 2 3 1
    2 2 2 3 1 2
    2 2 1 3 1 2
    2 1 1 3 3

    Output

    3

    思路:

    很明显的最大流题目。这道题匈牙利会超时,正解是Dinic
    这道题最难的也就是考点是建图。很容易想到这样的建法(权值均为1):
    这里写图片描述
    但是这样的话,就有可能一头牛吃多个食物及饮料,例如上图中牛1可以既吃食物1,饮料2组成的套餐,又可以吃食物2,饮料d组成的套餐。
    所以,这里就要拆点。将一头牛拆成两头,中间连一条权值为1的线,就可以保证不会有一头牛吃多组套餐的情况。
    这里写图片描述


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #define Inf 0x7f
    #define INF 2147483647
    using namespace std;
    
    int n,f,d,s,t,ans,sum,num,fnum,dnum,x,k,head[5000001],dep[5000001];
    
    struct edge
    {
        int c,to,next;
    }e[5000001];
    
    void add(int from,int to,int c)
    {
        k++;
        e[k].to=to;
        e[k].c=c;
        e[k].next=head[from];
        head[from]=k;
    }
    
    bool bfs()  //分层
    {
        memset(dep,Inf,sizeof(dep));
        queue<int> q;
        q.push(s);
        dep[s]=0;
        while (q.size())
        {
            int u=q.front();
            q.pop();
            for (int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if (dep[v]>dep[u]+1&&e[i].c)
                {
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
        return (dep[t]<Inf);
    }
    
    int dfs(int u,int low)
    {
        int lows=0;
        if (u==t) return low;
        for (int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if (dep[v]==dep[u]+1&&e[i].c) 
            {
                lows=dfs(v,min(low,e[i].c));  //继续找增广路
                if (!lows) continue;
                e[i].c-=lows;  //正向边
                e[(i+1)^1-1].c+=lows;  //反向边
                return lows;
            }
        }
        return 0;
    }
    
    int main()
    {
        //建图时牛a编号为1~n,牛b编号为n+1~2n,食物编号为2n+1~2n+f,饮料编号为2n+f+1~2n+f+d
        scanf("%d%d%d",&n,&f,&d);
        s=0;
        t=n+n+f+d+1;
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d",&fnum,&dnum);
            for (int j=1;j<=fnum;j++)  //食物连向牛a
            {
                scanf("%d",&x);
                add(n+n+x,i,1);
                add(i,n+n+x,0);
            }
            for (int j=1;j<=dnum;j++)  //牛b连向饮料
            {
                scanf("%d",&x);
                add(n+i,n+n+f+x,1);
                add(n+n+f+x,n+i,0);
            }
        }
        for (int i=1;i<=n;i++)  //牛a连向牛b
        {
            add(i,n+i,1);
            add(n+i,i,0);
        }
        for (int i=1;i<=f;i++)  //S连向食物
        {
            add(s,n+n+i,1);
            add(n+n+i,s,0);
        }
        for (int i=1;i<=d;i++)  //饮料连向T
        {
            add(n+n+f+i,t,1);
            add(t,n+n+f+i,0);
        }
        while (bfs())
        {
            while (sum=dfs(s,INF))
             ans+=sum;  
        }
        printf("%d\n",ans);
        return 0;
    }
  • 相关阅读:
    分布式缓存系统Memcached
    HTTP(GET/POST)请求过程中的编码问题
    将指定的Json字符串转为指定的T类型对象(转帖)
    Linux 中有几个文件压缩和解压缩工
    策略添加-通过域策略组自动映射共享文件夹
    Centos 7 加AD域
    Gns3 模拟器创建VLAN
    防火墙常用命令
    Centos 6 任务计划配置
    Cenots 7 开启 SSH_远程连接
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998811.html
Copyright © 2011-2022 走看看