zoukankan      html  css  js  c++  java
  • 2768: [JLOI2010]冠军调查( 最小割 )

    最小割... 怎么乱搞都可以

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #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 maxn = 300 + 5;
     
    struct edge {
    int to, cap;
    edge *next, *rev;
    };
     
    edge* pt;
    edge* head[ maxn ];
    edge EDGE[ maxn * maxn << 1 ];
     
    void init() {
    pt = EDGE;
    clr( head, 0 );
    }
     
    inline void add( int u, int v, int d ) {
    pt -> to = v;
    pt -> cap = d;
    pt -> next = head[ u ];
    head[ u ] = pt++;
    }
     
    inline void add_edge( int u, int v, int d ) {
    add( u, v, d );
    add( v, u, 0 );
    head[ u ] -> rev = head[ v ];
    head[ v ] -> rev = head[ u ];
    }
     
    edge *p[ maxn ], *cur[ maxn ];
    int d[ maxn ], cnt[ maxn ];
     
    int maxFlow( int S, int T , int N ) {
    clr( d, 0 );
    clr( cnt, 0 );
    cnt[ 0 ] = N;
    rep( i, N ) cur[ i ] = head[ i ];
    const int INF = 0x7fffffff;
    int flow = 0, x = S, A = INF;
    edge* e;
    while( d[ S ] < N ) {
    for( e = cur[ x ]; e; e = e -> next)
       if( d[ e -> to ] + 1 == d[ x ] && e -> cap > 0) break;
       
    if( e ) {
    p[ e -> to ] = cur[ x ] = e;
    A = min( A, e -> cap );
    x = e -> to;
    if( x == T ) {
    while( x != S ) {
    p[ x ] -> cap -= A;
    p[ x ] -> rev -> cap += A;
    x = p[ x ] -> rev -> to;
    }
    flow += A;
    A = INF;
    }
    } else {
    if( ! --cnt[ d[ x ] ] ) break;
    d[ x ] = N;
    for( e = head[ x ]; e; e = e -> next )
       if( d[ e -> to ] + 1 < d[ x ] && e -> cap > 0) {
        d[ x ] = d[ e -> to ] + 1;
        cur[ x ] = e;
       }
    cnt[ d[ x ] ]++;
    if( x != S ) x = p[ x ] -> rev ->to;
    }
    }
    return flow;
    }
    int main() {
    init();
    int n, m;
    cin >> n >> m;
    int s = 0, t = n + 1;
    Rep( i, n ) {
    int x;
    scanf( "%d", &x );
    x ? add_edge( s, i, 1 ) : add_edge( i, t, 1 );
    }
    while( m-- ) {
    int u, v;
    scanf( "%d%d", &u, &v );
    add_edge( u, v, 1 );
    add_edge( v, u, 1 );
    }
    cout << maxFlow( s, t, t + 1 ) << " ";
    return 0;
    }

      

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

    2768: [JLOI2010]冠军调查

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 642  Solved: 451
    [Submit][Status][Discuss]

    Description

    一年一度的欧洲足球冠军联赛已经进入了淘汰赛阶段。随着卫冕冠军巴萨罗那的淘汰,英超劲旅切尔西成为了头号热门。新浪体育最近在吉林教育学院进行了一次大规模的调查,调查的内容就是关于切尔西能否在今年问鼎欧洲冠军。新浪体育的记者从各个院系中一共抽取了n位同学作为参与者,大家齐聚一堂,各抒己见。每一位参与者都将发言,阐述自己的看法。参与者的心里都有一个看法,比如FireDancer认为切尔西不可能夺冠,而WaterDancer认为切尔西一定问鼎。但是因为WaterDancer是FireDancer的好朋友,所以可能FireDancer为了迁就自己的好朋友,会在发言中支持切尔西。也就是说每个参与者发言时阐述的看法不一定就是心里所想的。现在告诉你大家心里的想法和参与者的朋友网,希望你能安排每个人的发言内容,使得违心说话的人的总数与发言时立场不同的朋友(对)的总数的和最小。
     

    Input

    第一行两个整数n和m,其中n(2≤n≤300)表示参与者的总数,m(0≤m≤n(n-1)/2)表示朋友的总对数。
    第二行n个整数,要么是0要么是1。如果第i个整数的值是0的话,表示第i个人心里认为切尔西将与冠军无缘,如果是1的话,表示他心里认为切尔西必将夺魁。
    下面m行每行两个不同的整数,i和j(1≤i, j≤n)表示i和j是朋友。注意没有一对朋友会在输入中重复出现。朋友关系是双向的,并且不会传递。
     

    Output

     
    只有一个整数,为最小的和。

    Sample Input

    3 3
    1 0 0
    1 2
    1 3
    2 3

    Sample Output

    1

    HINT

    最好的安排是所有人都在发言时说切尔西不会夺冠。这样没有一对朋友的立场相左,只有第1个人他违心说了话。

    Source

  • 相关阅读:
    [转] 余国藩:人文学科何以不是科学
    [openssl][nginx] 使用openssl模拟ssl/tls客户端测试nginx stream
    [openssl] 使用openssl生成证书
    [bluez] linux下蓝牙鼠标的延迟问题
    很好的一篇文章讲epoll
    [ipsec][strongswan] VirtualPN隧道网络加速FEC(forward error correction)
    [ipsec][crypto] ike/ipsec与tls的认证机制比较
    [ipsec][crypto] 有点不同的数字证书到底是什么
    [ike][ipsec] child sa rekey机制的细节分析
    [dev][nginx] 在阅读nginx代码之前都需要准备什么
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4525021.html
Copyright © 2011-2022 走看看