zoukankan      html  css  js  c++  java
  • 【bzoj1711/Usaco2007 Open】Dining吃饭——网络流

    Description

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

    Input

    * 第一行: 三个数: N, F, 和 D

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

    Output

    * 第一行: 一个整数,最多可以喂饱的牛数.

    Sample 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

    输入解释:

    牛 1: 食品从 {1,2}, 饮料从 {1,2} 中选
    牛 2: 食品从 {2,3}, 饮料从 {1,2} 中选
    牛 3: 食品从 {1,3}, 饮料从 {1,2} 中选
    牛 4: 食品从 {1,3}, 饮料从 {3} 中选

    Sample Output

    3
     

     
    听说是三分图啊???就是从源向食物连一条权值为1的边,从饮料向汇连一条权值为1的边,将一头牛x拆成两个点x和x',从该牛能吃的食物向x和x'向能喝的饮料连边,权值也为1。然后跑一遍最大流即可。
    代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 const int N=105,inf=0x3f3f3f3f;
     5 long long an=0;
     6 int n,D,F,T,tot=1,m=100;
     7 int cur[N*4],first[N*4],d[N*4],q[N*4];
     8 struct node{
     9     int ne,to,w;
    10 }e[500500];
    11 int read(){
    12     int ans=0,f=1;char c=getchar();
    13     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    14     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    15     return ans*f;
    16 }
    17 void ins(int u,int v,int w){
    18     e[++tot]=(node){first[u],v,w};first[u]=tot;
    19     e[++tot]=(node){first[v],u,0};first[v]=tot;
    20 }
    21 bool bfs(){
    22     memset(d,-1,sizeof(d));d[0]=0;q[0]=0;
    23     int h=0,t=1;
    24     while(h!=t){
    25         int x=q[h++];if(h>=400)h=0;
    26         for(int i=first[x];i;i=e[i].ne){
    27             int to=e[i].to;
    28             if(d[to]==-1&&e[i].w>0){
    29                 d[to]=d[x]+1;
    30                 q[t++]=to;if(t>=400)t=0;
    31             }
    32         }
    33     }
    34     if(d[T]==-1)return 0;
    35     return 1;
    36 }
    37 int dfs(int x,int a){
    38     if(x==T||!a)return a;
    39     int flow=0,f;
    40     for(int &i=cur[x];i;i=e[i].ne){
    41         int to=e[i].to;
    42         if(d[to]==d[x]+1&&(f=dfs(to,std::min(e[i].w,a)))>0){
    43             e[i].w-=f;
    44             e[i^1].w+=f;
    45             flow+=f;
    46             a-=f;
    47             if(!a)break;
    48         }
    49     }
    50     return flow;
    51 }
    52 int main(){
    53     n=read();F=read();D=read();
    54     T=4*m+1;
    55     for(int i=1;i<=F;i++)ins(0,2*m+i,1);
    56     for(int i=1;i<=D;i++)ins(3*m+i,T,1);
    57     for(int i=1;i<=n;i++)ins(i,i+m,1);
    58     for(int i=1,d,f;i<=n;i++){
    59         f=read();d=read();int a;
    60         while(f--)a=read(),ins(2*m+a,i,1);    
    61         while(d--)a=read(),ins(m+i,3*m+a,1);
    62     }
    63     while(bfs()){
    64         for(int i=0;i<=T;i++)cur[i]=first[i];
    65         an+=dfs(0,inf);
    66     }
    67     printf("%lld",an);
    68     return 0;
    69 }
    bzoj1711
  • 相关阅读:
    [算法初步]希尔排序
    逆波兰表达式1(简介)
    [数据结构]之链表
    [数据结构]之栈
    [算法初步]之归并排序
    [算法初步]之快速排序
    [算法初步]之冒泡排序
    逆波兰表达式2中缀转后缀表达式)
    [算法初步]之简单选择排序
    [数据结构]之顺序表
  • 原文地址:https://www.cnblogs.com/JKAI/p/7536813.html
Copyright © 2011-2022 走看看