题意: 给你一个N * M 的图 ,然后用1 *2 的卡片去覆盖,有些点是不能覆盖的。问是否可以完全覆盖
直接二分匹配找出最大匹配是否等于能覆盖的点数。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 2005 #define inf 1<<28 #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define Rep(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) using namespace std; struct kdq { int e ,next ; } ed[Max * 10] ; int head[Max] , num ; void add(int s ,int e ) { ed[num].e = e ; ed[num].next = head[s] ; head[s] = num ++ ; } int link[Max] ; bool vis[Max] ; int dfs(int x ) { for (int i = head[x] ; i != -1 ; i = ed[i].next ) { int e = ed[i].e ; if(!vis[e]) { vis[e] = 1 ; if(link[e] == -1 || dfs(link[e])) { link[e] = x ; return 1 ; } } } return 0 ; } int Map[50][50] ; int n ,m , k ; int mx[4] = {0 ,0 , 1 ,-1} ; int my[4] = {1 ,-1, 0 , 0} ; int inmap(int x ,int y ) { if(x >= 1 && x <= n &&y >= 1 && y <= m &&!Map[x][y]) return 1 ; return 0 ; } int Mapnum[50][50] ; int nn = 0 ; void init() { mem(vis,0) ; mem(head,-1) ; mem(link,-1) ; mem(Map,0) ; mem(Mapnum,0) ; nn = 0 ; } void build() { for (int i = 1 ; i <= n; i ++ ) { for (int j = 1 ; j <= m ; j ++ ) { if(Map[i][j] == 0) Mapnum[i][j] = ++ nn ; } } for (int i = 1 ; i <= n; i ++ ) { for (int j = 1 ; j <= m ; j ++ ) { if(!Map[i][j]) { for (int k = 0 ; k < 4 ; k ++ ) { int tx = i + mx[k] ; int ty = j + my[k] ; if(inmap(tx,ty)) { add(Mapnum[i][j] ,Mapnum[tx][ty]) ; } } } } } } int main() { while(cin >> n >> m >> k) { init() ; int d = k ; while(d -- ) { int a , b ; scanf("%d%d",&a,&b) ; Map[b][a] = 1 ; } build() ; int ans = 0 ; for (int i = 1 ; i <= nn ; i ++ ) { mem(vis,0) ; ans += dfs(i) ; } int cnt = n * m - k ; if((cnt & 1) || (ans != cnt ) ) cout <<"NO"<<endl; else cout <<"YES"<<endl; } return 0; }