• BZOJ 1475: 方格取数( 网络流 )


    本来想写道水题....结果调了这么久!就是一个 define 里面少加了个括号 !

    二分图最大点权独立集...黑白染色一下 , 然后建图 :

    S -> black_node , white_node -> T , 流量都为点权 . 然后 black_node -> white_node ( 两点有公共边 ) , 流量为 +oo , 然后 answer = ∑ w( i ) ( i ∈ V ) - maxflow

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
      
    #define rep( i , n ) for( int i = 0 ; i < n ; ++i )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
    #define id( x , y ) ( ( x ) * n + y + 1 )
      
    using namespace std;
      
    const int inf = 0x7fffffff;
    const int maxn = 1000;
      
    struct edge {
    int to , cap;
    edge *next , *rev;
    } E[ maxn << 3 ] , *pt = E , *head[ maxn ];
      
    inline void add_edge( int u , int v , int w ) {
    pt -> to = v;
    pt -> cap = w;
    pt -> next = head[ u ];
    head[ u ] = pt++;
    pt -> to = u;
    pt -> cap = 0;
    pt -> next = head[ v ];
    head[ v ] = pt++;
    head[ u ] -> rev = head[ v ];
    head[ v ] -> rev = head[ u ];
    }
      
    int h[ maxn ] , cnt[ maxn ] , S , T , N;
    edge *cur[ maxn ] , *p[ maxn ];
      
    int maxFlow() {
    clr( h , 0 ) , clr( cnt , 0 );
    cnt[ 0 ] = N;
    rep( i , N ) cur[ i ] = head[ i ];
    int flow = 0 , A = inf;
    edge* e;
    for( int x = S ; h[ S ] < N ; ) {
    for( e = cur[ x ] ; e ; e = e -> next ) 
       if( h[ e -> to ] + 1 == h[ x ] && e -> cap ) break;
    if( e ) {
    A = min( A , e -> cap );
    p[ e -> to ] = cur[ x ] = e;
    if( ( x = e -> to ) == 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 && 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 );
    clr( head , 0 );
    int ans = 0 , n;
    cin >> n;
    S = 0 , T = n * n + 1 , N = T + 1;
    rep( i , n ) 
       rep( j , n ) {
        int w;
        scanf( "%d" , &w );
        ans += w;
        if( ( i + j ) & 1 ) {
           add_edge( S , id( i , j ) , w );
           if( i ) add_edge( id( i , j ) , id( i - 1 , j ) , inf );
           if( j ) add_edge( id( i , j ) , id( i , j - 1 ) , inf );
           if( i + 1 < n ) add_edge( id( i , j ) , id( i + 1 , j ) , inf );
           if( j + 1 < n ) add_edge( id( i , j ) , id( i , j + 1 ) , inf );
        } else
           add_edge( id( i , j ) , T , w );
       }
    cout << ans - maxFlow() << " ";
    return 0;

       

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

    1475: 方格取数

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 616  Solved: 323
    [Submit][Status][Discuss]

    Description

    在一个n*n的方格里,每个格子里都有一个正整数。从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大。

    Input

    第一行一个数n;(n<=30) 接下来n行每行n个数描述一个方阵

    Output

    仅一个数,即最大和

    Sample Input

    2
    1 2
    3 5

    Sample Output

    6

    HINT

    Source

  • 相关阅读:
    个人软件过程 1
    一个月学会VC++2012 3.我们动手吧!
    一个月掌握VC++2010?
    个人软件过程2 项目开发的基本流程
    个人软件过程4 功能说明和用户体验设计
    一个月学会VC++2010 5.对话框的数据交换
    个人软件过程3 需求分析
    一个月学会VC++2010 4.细说对象之香艳旖旎
    一个月学会VC++2010 1.送上门的银子
    一个月学会VC++2010 2.看起来风险不大
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4649863.html
Copyright © 2020-2023  润新知