• 【JZOJ1611】Dining


    题目描述

      农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食。每一头牛只喜欢吃一些食品和饮料而别的一概不吃。虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料。
      农夫JOHN做了F (1<=F<=100) 种食品和准备了D(1<=D<=100)种饮料。他有N(1<=N<=100)头牛,现在已经知道他的每头牛是否愿意吃某种食物和喝某种饮料。农夫JOHN想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料。
      每一件食物和饮料只能由一头牛来用。例如如果食物2被一头牛吃掉了,没有别的牛能吃食物2。

    输入

      第一行: 三个数:N, F和D。
      第2..N+1行:每一行有两个数开始F_i和D_i,分别是第i头牛可以吃的食品数和可以喝的饮料数。接下来下F_i个整数是第i头牛可以吃的食品号,再下面的D_i个整数是第i头牛可以喝的饮料号码。

    输出

      文件输出仅一行为一个整数,表示最多可以喂饱牛的数目。

    样例输入

    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

    样例输出

    3

    解法

    网络流建模:
    源点向每个食物连一条容量为1的边;
    每头牛拆成两个点xi,yi,这两个点连一条容量为1的边;
    这头牛的喜好食物向xi连一条容量为1的边,yi向喜好饮品连一条容量为1的边;
    每个饮品向汇点连一条容量为1的边。


    检验:
    每头牛只能占用一个饮品和食品,所以把牛拆点。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    #define sqr(x) ((x)*(x))
    #define ln(x,y) int(log(x)/log(y))
    #define food(x) (1+x)
    #define drink(x) (1+m1+x)
    #define cow(x) (1+m1+m2+x)
    #define cow1(x) (1+m1+m2+n+x)
    using namespace std;
    const char* fin="ex1611.in";
    const char* fout="ex1611.out";
    const int inf=0x7fffffff;
    const int maxn=1007,maxm=maxn*10;
    int n,m1,m2,i,j,k,ans=0;
    int num,tot=1,fi[maxn],ne[maxm],la[maxm],va[maxm];
    int bz[maxn],cnt[maxn];
    void add_line(int a,int b,int c){
        tot++;
        ne[tot]=fi[a];
        la[tot]=b;
        va[tot]=c;
        fi[a]=tot;
    }
    void add(int a,int b,int c){
        add_line(a,b,c);
        add_line(b,a,0);
    }
    int gap(int v,int flow){
        int i,use=0,k;
        if (v==num) return flow;
        for (k=fi[v];k;k=ne[k])
            if (va[k] && bz[v]==bz[la[k]]+1){
                i=gap(la[k],min(va[k],flow-use));
                use+=i;
                va[k]-=i;
                va[k^1]+=i;
                if (use==flow || bz[1]==num) return use;
            }
        if (!--cnt[bz[v]]) bz[1]=num;
        cnt[++bz[v]]++;
        return use;
    }
    int main(){
        scanf("%d%d%d",&n,&m1,&m2);
        num=1+m1+m2+n+n+1;
        for (i=1;i<=n;i++){
            int iiii;
            add(cow(i),cow1(i),1);
            scanf("%d",&j);
            scanf("%d",&iiii);
            for (;j;j--){
                scanf("%d",&k);
                add(food(k),cow(i),1);
            }
            for (;iiii;iiii--){
                scanf("%d",&k);
                add(cow1(i),drink(k),1);
            }
        }
        for (i=1;i<=m1;i++) add(1,food(i),1);
        for (i=1;i<=m2;i++) add(drink(i),num,1);
        cnt[0]=num;
        while (bz[1]<num) ans+=gap(1,inf);
        printf("%d",ans);
        return 0;
    } 

    启发

    通过拆点来限制每头牛的贡献。

  • 相关阅读:
    js怎么把一个数组里面的值作为一个属性添加到另一数组包含的对象里(小程序)
    h5调用手机相册摄像头以及文件夹
    tomcat7之性能优化
    数组和集合详解及项目中的运用
    Jackson 解析json数据之忽略解析字段注解@JsonIgnoreProperties
    JSON解析及数据库操作实战篇
    jdk及tomcat的安装
    append、replace、replaceAll、indexof、lastIndexOf、substring、split、match的用法
    Spring JdbcTemplate详解及项目中的运用
    JSON解析
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714865.html
Copyright © 2020-2023  润新知