题目链接:http://poj.org/problem?id=2446 题意:给你一个 m*n的棋盘,要你用1×2大小的卡片覆盖它,并且每个方格都只能被一个卡片覆盖。其中k个方格不能放卡片。(0 < m, n <= 32, 0 <= K < m * n) 思路:将这个棋盘想象成国际象棋的黑白相间的棋盘,黑格和其上下左右的四个白格匹配即可建成一个二分图,当然不能放卡片的那几个格子要过滤掉。 注意:这里是 m行 n列!先输入的是m。在程序里将m和n调换也可以。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#define pi acos(-1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair< int , int > PII;
typedef pair< LL, LL> PLL;
const int INF = 0x3f3f3f3f ;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f ;
const int maxn = 32 + 10 ;
const int maxm = 32 + 10 ;
const int maxv = 10000 + 10 ;
const int maxe = 20000 + 10 ;
const int mod = 1e9 + 7 ;
int mp[ 40 ] [ 40 ] ;
int dir[ 4 ] [ 2 ] = { 0 , 1 , 0 , - 1 , 1 , 0 , - 1 , 0 } ;
int S, T;
int head[ maxe] , tot= 0 , nowedge[ maxe] ;
int dis[ maxv] ;
int vis[ maxv] ;
struct Edge
{
int to, next, cap;
} es[ maxe] ;
int read ( ) {
int x= 0 , f= 1 ; char ch= getchar ( ) ;
while ( ch< '0' || ch> '9' ) { if ( ch== '-' ) f= - 1 ; ch= getchar ( ) ; }
while ( ch>= '0' && ch<= '9' ) { x= x* 10 + ch- '0' ; ch= getchar ( ) ; }
return x* f;
}
void init ( )
{
memset ( head, - 1 , sizeof ( head) ) ;
memset ( vis, 0 , sizeof ( vis) ) ;
tot= 0 ;
}
void add ( int u, int v, int vol)
{
es[ tot] . to = v;
es[ tot] . cap = vol;
es[ tot] . next = head[ u] ;
head[ u] = tot++ ;
es[ tot] . to = u;
es[ tot] . cap = 0 ;
es[ tot] . next = head[ v] ;
head[ v] = tot++ ;
}
bool BFS ( )
{
queue< int > que;
memset ( dis, - 1 , sizeof ( dis) ) ;
dis[ S] = 0 ;
que. push ( S) ;
int cur, v;
while ( ! que. empty ( ) )
{
cur = que. front ( ) ; que. pop ( ) ;
for ( int i= head[ cur] ; i!= - 1 ; i= es[ i] . next) {
v = es[ i] . to;
if ( dis[ v] == - 1 && es[ i] . cap> 0 ) {
dis[ v] = dis[ cur] + 1 ;
que. push ( v) ;
}
}
}
if ( dis[ T] == - 1 ) return false;
else return true;
}
LL DFS ( int cur, LL low)
{
LL res= 0 , add= 0 ;
if ( cur == T) return low;
for ( int i= nowedge[ cur] ; i!= - 1 ; i= es[ i] . next) {
nowedge[ cur] = i;
if ( dis[ es[ i] . to] == dis[ cur] + 1
&& es[ i] . cap> 0
&& ( add = DFS ( es[ i] . to, min ( low, ( LL) es[ i] . cap) ) ) ) {
es[ i] . cap - = add;
es[ i^ 1 ] . cap + = add;
low - = add;
res + = add;
if ( low == 0 ) break ;
}
}
if ( res == 0 ) dis[ cur] = 0 ;
return res;
}
LL MAXFLOW ( )
{
LL ans= 0 , tmp= 0 ;
while ( BFS ( ) ) {
for ( int i= S; i<= T; i++ ) {
nowedge[ i] = head[ i] ;
}
if ( tmp = DFS ( S, INF) )
ans + = tmp;
}
return ans;
}
int left_net ( int cur)
{
vis[ cur] = 1 ;
int ans = 1 ;
for ( int i= head[ cur] ; i!= - 1 ; i = es[ i] . next) {
if ( es[ i] . cap > 0 && ! vis[ es[ i] . to] ) ans + = left_net ( es[ i] . to) ;
}
return ans;
}
int main ( )
{
int n, m, k;
init ( ) ;
scanf ( "%d%d%d" , & n, & m, & k) ;
S = 0 ;
T = n* m+ 1 ;
int tmp1, tmp2;
for ( int i= 0 ; i< k; i++ ) {
scanf ( "%d%d" , & tmp2, & tmp1) ;
mp[ tmp1] [ tmp2] = 1 ;
}
for ( int i= 1 ; i<= n; i++ ) {
for ( int j= 1 ; j<= m; j++ ) {
if ( mp[ i] [ j] ) continue ;
if ( ( i+ j) % 2 == 1 ) {
add ( S, ( i- 1 ) * m+ j, 1 ) ;
for ( int dd= 0 ; dd< 4 ; dd++ ) {
int x = i+ dir[ dd] [ 0 ] ;
int y = j+ dir[ dd] [ 1 ] ;
if ( mp[ x] [ y] != 1 && x>= 1 && x<= n && y>= 1 && y<= m) {
add ( ( i- 1 ) * m+ j, ( x- 1 ) * m+ y, INF) ;
}
}
}
else add ( ( i- 1 ) * m+ j, T, 1 ) ;
}
}
LL ans = MAXFLOW ( ) ;
if ( ans* 2 != ( n* m- k) ) printf ( "NO\n" ) ;
else printf ( "YES\n" ) ;
}