• BZOJ 1711: [Usaco2007 Open]Dingin吃饭( 最大流 )


    将牛拆成两个点 i 和 i' 并连弧 , S 向每种 food 连边 , 每种 drink 向 T 连边 , 每种 food 向喜欢他的 cow 连边 到 i , 每种 drink 从喜欢它的 cow i' 连边 , 全部容量均为 1 , answer = maxflow 

    --------------------------------------------------------------------------------

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
     
    #define rep( i , n ) for( int i = 0 ; i < n ; ++i )
    #define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
     
    using namespace std;
     
    const int INF = 0x7fffffff;
    const int maxn = 400 + 5;
     
    struct edge {
    int to , cap;
    edge *next , *rev;
    };
     
    edge* pt , EDGE[ 20305 << 1 ];
    edge* head[ maxn ];
     
    void init() {
    pt = EDGE;
    clr( head , 0 );
    }
     
    void add( int u , int v , int c ) {
    pt -> to = v;
    pt -> cap = c;
    pt -> next = head[ u ];
    head[ u ] = pt++;
    }
     
    void add_edge( int u , int v , int c ) {
    add( u , v , c );
    add( v , u , 0 );
    head[ u ] -> rev = head[ v ];
    head[ v ] -> rev = head[ u ];
    }
     
    edge *p[ maxn ] , *cur[ maxn ];
    int h[ maxn ] , cnt[ maxn ];
     
    int maxFlow( int S , int T , int N ) {
    clr( h , 0 );
    clr( cnt , 0 );
    rep( i , N ) 
       cur[ i ] = head[ i ];
    cnt[ 0 ] = N;
    int x = S , flow = 0 , A = INF;
    edge* e;
    while( h[ S ] < N ) {
    for( e = cur[ x ] ; e ; e = e -> next )
       if( e -> cap > 0 && h[ e -> to ] + 1 == h[ x ] ) break;
       
    if( e ) {
    p[ e -> to ] = cur[ x ] = e;
    A = min( A , e -> cap );
    x = e -> to;
    if( x == T ) {
    for( ; x != S ; x = p[ x ] -> rev -> to ) {
    p[ x ] -> cap -= A;
    p[ x ] -> rev -> cap += A;
    }
    flow += A;
    A = INF;
    }
    } else {
    if( ! --cnt[ h[ x ] ] ) break;
    h[ x ] = N;
    for( e = head[ x ] ; e ; e = e -> next ) 
       if( e -> cap > 0 && h[ e -> to ] + 1 < h[ x ] ) {
        h[ x ] = h[ e -> to ] + 1;
        cur[ x ] = e;
       }
    ++cnt[ h[ x ] ];
    if( x != S ) x = p[ x ] -> rev -> to;
    }
    }
    return flow;
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    init();
    int n , f , d;
    cin >> n >> f >> d;
    int S = 0 , T = ( n << 1 ) + f + d + 1;
    Rep( i , n )
       add_edge( i , i + f + d + n , 1 );
    Rep( i , f )
       add_edge( S , n + i , 1 );
    Rep( i , d )
       add_edge( n + f + i , T , 1 );
    Rep( i , n ) {
    int F , D;
    scanf( "%d%d" , &F , &D );
    int t;
    while( F-- ) {
    scanf( "%d" , &t );
    add_edge( t + n , i , 1 );
    }
    while( D-- ) {
    scanf( "%d" , &t );
    add_edge( i + f + d + n , t + n + f , 1 );
    }
    }
    cout << maxFlow( S , T , T + 1 ) << " ";
    return 0;
    }

    -------------------------------------------------------------------------------- 

    1711: [Usaco2007 Open]Dingin吃饭

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 568  Solved: 294
    [Submit][Status][Discuss]

    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
    输出解释:

    一个方案是:
    Cow 1: 不吃
    Cow 2: 食品 #2, 饮料 #2
    Cow 3: 食品 #1, 饮料 #1
    Cow 4: 食品 #3, 饮料 #3
    用鸽笼定理可以推出没有更好的解 (一共只有3总食品和饮料).当然,别的数据会更难.

    HINT

    Source

  • 相关阅读:
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1041:奇偶数判断
    1040:输出绝对值
    1040:输出绝对值
    1040:输出绝对值
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1039:判断数正负
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1039:判断数正负
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1039:判断数正负
    Winform应用程序实现通用遮罩层
    SQL WITH子句、分析函数
    SQL WITH子句、分析函数
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4565851.html
Copyright © 2020-2023  润新知