BZOJ-2150: 部落战争(二分图匹配)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2150

赤裸裸的一道最小路径覆盖,直接上匈牙利或网络流即可。

代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
 
using namespace std ;
 
#define maxv maxn * maxn
#define maxn 51
#define check( x , y ) ( x > 0 && y > 0 && x <= n && y <= m && s[ x ][ y ] == '.' )
 
struct Match {
 
    struct edge {
        int t ;
        edge *next ;
    } *head[ maxv ] ;
 
    int match[ maxv ] ;
    bitset < maxv > used ;
 
    Match(  ) {
        memset( head , 0 , sizeof( head ) ) ;
        memset( match , 0 , sizeof( match ) ) ;
    }
 
    void AddEdge( int s , int t ) {
        edge *p = new( edge ) ;
        p -> t = t , p -> next = head[ s ] ; 
        head[ s ] = p ;
    }
 
    bool dfs( int v ) {
        for ( edge *p = head[ v ] ; p ; p = p -> next ) if ( ! used[ p -> t ] ) {
            used[ p -> t ] = true ;
            if ( ! match[ p -> t ] || dfs( match[ p -> t ] ) ) {
                match[ p -> t ] = v ; 
                return true ;
            }
        }
        return false ;
    }
 
    int max_match( int v ) {
        int cnt = 0 ; 
        for ( int i = 0 ; i ++ < v ; ) {
            used.reset(  ) ;
            if ( dfs( i ) ) ++ cnt ;
        }
        return cnt ;
    }
 
} mat ;
 
int node[ maxn ][ maxn ] , n , m , V = 0 , r , c ;
char s[ maxn ][ maxn ] ;
 
int main(  ) {
    scanf( "%d%d%d%d" , &n , &m , &r , &c ) ;
    for ( int i = 0 ; i ++ < n ; ) {
        scanf( "%s" , s[ i ] + 1 ) ;
        for ( int j = 0 ; j ++ < m ; ) if ( s[ i ][ j ] == '.' ) {
            node[ i ][ j ] = ++ V ;
        }
    }
    for ( int i = 0 ; i ++ < n ; ) for ( int j = 0 ; j ++ < m ; ) if ( s[ i ][ j ] == '.' ) {
        int x = i + r , y = j + c ;
        if ( check( x , y ) ) mat.AddEdge( node[ i ][ j ] , node[ x ][ y ] ) ;
        x = i + r , y = j - c ;
        if ( check( x , y ) ) mat.AddEdge( node[ i ][ j ] , node[ x ][ y ] ) ;
        x = i + c , y = j + r ;
        if ( check( x , y ) ) mat.AddEdge( node[ i ][ j ] , node[ x ][ y ] ) ;
        x = i + c , y = j - r ;
        if ( check( x , y ) ) mat.AddEdge( node[ i ][ j ] , node[ x ][ y ] ) ;
    }
    printf( "%d\n" , V - mat.max_match( V ) ) ;
    return 0 ; 
}
    原文作者:AmadeusChan
    原文地址: https://www.jianshu.com/p/f65cdd719408
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞